¿Qué significa el error "No se puede encontrar el símbolo" o "No se puede resolver el símbolo"?

Resuelto Stephen C asked hace 10 años • 18 respuestas

Explique lo siguiente sobre los errores "No se puede encontrar el símbolo", "No se puede resolver el símbolo" o "Símbolo no encontrado" (en Java):

  • ¿Qué quieren decir?
  • ¿Qué cosas pueden causarlos?
  • ¿Cómo hace el programador para solucionarlos?

Esta pregunta está diseñada para generar una sesión completa de preguntas y respuestas sobre estos errores de compilación comunes en Java.

Stephen C avatar Sep 07 '14 08:09 Stephen C
Aceptado

0. ¿Existe alguna diferencia entre estos errores?

No precisamente. "No se puede encontrar el símbolo", "No se puede resolver el símbolo" y "Símbolo no encontrado" significan lo mismo. (Los diferentes compiladores de Java están escritos por personas diferentes, y diferentes personas usan fraseología diferente para decir lo mismo).

1. ¿Qué significa el error "No se puede encontrar el símbolo"?

En primer lugar, se trata de un error de compilación 1 . Significa que hay un problema en su código fuente de Java o hay un problema en la forma en que lo está compilando.

Su código fuente Java consta de lo siguiente:

  • Palabras clave: me gusta class, whileetc.
  • Literales: como true, false, 42y 'X'."Hi mum!"
  • Operadores y otros tokens no alfanuméricos: como +, =, {etc.
  • Identificadores: como Reader, i, toString, processEquibalancedElephantsetc.
  • Comentarios y espacios en blanco.

El error "No se puede encontrar el símbolo" se debe a los identificadores. Cuando se compila su código, el compilador necesita determinar qué significan todos y cada uno de los identificadores de su código.

Un error "No se puede encontrar el símbolo" significa que el compilador no puede hacer esto. Su código parece hacer referencia a algo que el compilador no comprende.

2. ¿Qué puede causar el error "No se puede encontrar el símbolo"?

Como primer orden, sólo hay una causa. El compilador buscó en todos los lugares donde debería definirse el identificador y no pudo encontrar la definición. Esto podría deberse a varias cosas. Los comunes son los siguientes:

  • Para identificadores en general:

    • Quizás hayas escrito mal el nombre; es decir, StringBiulderen lugar de StringBuilder. Java no puede ni intentará compensar los errores ortográficos o tipográficos.
    • Quizás se equivocó en el caso; es decir, stringBuilderen lugar de StringBuilder. Todos los identificadores de Java distinguen entre mayúsculas y minúsculas.
    • Quizás usaste guiones bajos de manera inapropiada; es decir, mystringy my_stringson diferentes. (Si sigues las reglas de estilo de Java, estarás en gran medida protegido de este error...)
    • Quizás esté intentando utilizar algo que se declaró "en otro lugar"; es decir, en un contexto diferente al que implícitamente le ha indicado al compilador que mire. (¿Una clase diferente? ¿Un alcance diferente? ¿Un paquete diferente? ¿Una base de código diferente?)
  • Para identificadores que deben hacer referencia a variables:

    • Quizás olvidó declarar la variable.
    • Quizás la declaración de variable esté fuera de alcance en el momento en que intentó usarla. (Ver ejemplo a continuación)
  • Para identificadores que deberían ser nombres de métodos o campos:

    • Quizás esté intentando hacer referencia a un método o campo heredado que no se declaró en las clases o interfaces padre/ancestro.

    • Quizás esté intentando hacer referencia a un método o campo que no existe (es decir, que no ha sido declarado) en el tipo que está utilizando; por ejemplo, "rope".push()2 .

    • Quizás esté intentando utilizar un método como campo, o viceversa; por ejemplo "rope".lengtho someArray.length().

    • Quizás esté operando por error en una matriz en lugar de en un elemento de la matriz; p.ej,

          String strings[] = ...
          if (strings.charAt(3)) { ... }
          // Maybe that should be 'strings[0].charAt(3)'
      
  • Para identificadores que deberían ser nombres de clases:

    • Quizás olvidó importar la clase.

    • Quizás utilizó importaciones "estrella", pero la clase no está definida en ninguno de los paquetes que importó.

    • Quizás olvidaste un newcomo en:

          String s = String();  // Should be 'new String()'
      
    • Quizás esté intentando importar o utilizar una clase que ha sido declarada en el paquete predeterminado ; es decir, aquel donde packagevan las clases sin declaraciones.

      Sugerencia: aprenda sobre los paquetes. Sólo debe utilizar el paquete predeterminado para aplicaciones simples que constan de una clase... o, como mucho, un archivo fuente Java.

  • Para los casos en los que el tipo o la instancia no parece tener el miembro (por ejemplo, método o campo) que esperaba que tuviera:

    • Quizás haya declarado una clase anidada o un parámetro genérico que oculta el tipo que pretendía utilizar.
    • Quizás esté siguiendo una variable estática o de instancia.
    • Quizás importó el tipo incorrecto; por ejemplo, debido a que el IDE completó o la autocorrección puede haber sugerido java.awt.Listen lugar de java.util.List.
    • Quizás esté utilizando (compilando con) la versión incorrecta de una API.
    • Quizás olvidó convertir su objeto en una subclase apropiada.
    • Quizás haya declarado el tipo de variable como un supertipo de la que tiene el miembro que está buscando.

El problema suele ser una combinación de los anteriores. Por ejemplo, tal vez usted importó "estrella" java.io.*y luego intentó usar la Filesclase... que está en java.nionot java.io. O tal vez quisiste escribir File... que es una clase en java.io.


A continuación se muestra un ejemplo de cómo un alcance de variable incorrecto puede provocar el error "No se puede encontrar el símbolo":

List<String> strings = ...

for (int i = 0; i < strings.size(); i++) {
    if (strings.get(i).equalsIgnoreCase("fnord")) {
        break;
    }
}
if (i < strings.size()) {
    ...
}

Esto generará el error "No se puede encontrar el símbolo" ien la ifdeclaración. Aunque anteriormente declaramos i, esa declaración solo tiene alcance para la fordeclaración y su cuerpo. La referencia a ien la ifdeclaración no puede ver esa declaración de i. Está fuera de alcance .

(Una corrección apropiada aquí podría ser mover la ifdeclaración dentro del ciclo o declararla iantes del inicio del ciclo).


A continuación se muestra un ejemplo que causa perplejidad en el que un error tipográfico conduce a un error aparentemente inexplicable "No se puede encontrar el símbolo":

for (int i = 0; i < 100; i++); {
    System.out.println("i is " + i);
}

Esto le dará un error de compilación en la printlnllamada que indica que ino se puede encontrar. Pero (te oigo decir) ¡sí lo declaré!

El problema es el astuto punto y coma ( ;) antes del {. La sintaxis del lenguaje Java define un punto y coma en ese contexto como una declaración vacía . La declaración vacía se convierte entonces en el cuerpo del forbucle. Entonces ese código en realidad significa esto:

for (int i = 0; i < 100; i++);

// The previous and following are separate statements!!

{
    System.out.println("i is " + i);
}

El { ... }bloque NO es el cuerpo del forbucle y, por lo tanto, la declaración anterior de ien la fordeclaración está fuera del alcance del bloque.


Aquí hay otro ejemplo de error "No se puede encontrar el símbolo" causado por un error tipográfico.

int tmp = ...
int res = tmp(a + b);

A pesar de la declaración anterior, la tmpexpresión tmp(...)es errónea. El compilador buscará un método llamado tmpy no encontrará ninguno. Lo declarado previamente tmpestá en el espacio de nombres de las variables, no en el espacio de nombres de los métodos.

En el ejemplo que encontré, el programador había omitido a un operador. Lo que quería escribir era esto:

int res = tmp * (a + b);

Hay otra razón por la que es posible que el compilador no encuentre un símbolo si está compilando desde la línea de comando. Es posible que simplemente se haya olvidado de compilar o recompilar alguna otra clase. Por ejemplo, si tienes clases Fooy Bardónde Foose usa Bar. Si nunca ha compilado Bary ejecuta javac Foo.java, es probable que descubra que el compilador no puede encontrar el símbolo Bar. La respuesta simple es compilar Fooy Barjuntos; por ejemplo, javac Foo.java Bar.javao javac *.java. O mejor aún, utilice una herramienta de compilación de Java; por ejemplo, Ant , Maven , Gradle , etc.

También hay otras causas más oscuras... que abordaré a continuación.

3. ¿Cómo soluciono estos errores?

En términos generales, se comienza averiguando qué causó el error de compilación.

  • Mire la línea del archivo indicada por el mensaje de error de compilación.
  • Identifique de qué símbolo se refiere el mensaje de error.
  • Descubra por qué el compilador dice que no puede encontrar el símbolo; ¡véase más arriba!

Luego piensas en lo que se supone que dice tu código. Luego, finalmente, determina qué corrección necesita realizar en su código fuente para hacer lo que desea.

Tenga en cuenta que no todas las "correcciones" son correctas. Considera esto:

for (int i = 1; i < 10; i++) {
    for (j = 1; j < 10; j++) {
        ...
    }
}

Supongamos que el compilador dice "No se puede encontrar el símbolo" para j. Hay muchas maneras en que podría "arreglar" eso:

  • Podría cambiar el interior fora for (int j = 1; j < 10; j++)... probablemente correcto.
  • Podría agregar una declaración j antes del bucle interno foro del forbucle externo, posiblemente correcta.
  • Podría cambiar jal bucle iinterno for, ¡probablemente mal!
  • etcétera.

El punto es que necesita comprender qué intenta hacer su código para poder encontrar la solución correcta.

4. Causas oscuras

Aquí hay un par de casos en los que el símbolo "No se puede encontrar" es aparentemente inexplicable... hasta que miras más de cerca.

  1. Dependencias incorrectas : si está utilizando un IDE o una herramienta de compilación que administra la ruta de compilación y las dependencias del proyecto, es posible que haya cometido un error con las dependencias; por ejemplo, omitió una dependencia o seleccionó la versión incorrecta. Si está utilizando una herramienta de compilación (Ant, Maven, Gradle, etc.), verifique el archivo de compilación del proyecto. Si está utilizando un IDE, verifique la configuración de la ruta de compilación del proyecto.

  2. No se puede encontrar el símbolo 'var' : probablemente esté intentando compilar código fuente que utiliza inferencia de tipo de variable local (es decir, una vardeclaración) con un compilador anterior o un --sourcenivel anterior. Se varintrodujo en Java 10. Verifique su versión de JDK y sus archivos de compilación y (si esto ocurre en un IDE), la configuración del IDE.

  3. No estás compilando/recompilando : a veces sucede que los nuevos programadores de Java no entienden cómo funciona la cadena de herramientas de Java o no han implementado un "proceso de compilación" repetible; por ejemplo, usando un IDE, Ant, Maven, Gradle, etc. En tal situación, el programador puede terminar persiguiéndose la cola en busca de un error ilusorio que en realidad es causado por no recompilar el código correctamente, y cosas por el estilo.

    Otro ejemplo de esto es cuando usas (Java 9+) java SomeClass.javapara compilar y ejecutar una clase. Si la clase depende de otra clase que no ha compilado (o recompilado), es posible que obtenga errores del tipo "No se puede resolver el símbolo" en referencia a la segunda clase. Los demás archivos fuente no se compilan automáticamente. El javanuevo modo "compilar y ejecutar" del comando no está diseñado para ejecutar programas con múltiples archivos de código fuente.

  4. Un problema de compilación anterior : es posible que una compilación anterior haya fallado de manera que haya generado un archivo JAR al que le faltan clases. Este tipo de error normalmente se notaría si estuviera utilizando una herramienta de compilación. Sin embargo, si obtiene archivos JAR de otra persona, dependerá de que los cree correctamente y detecte errores. Si sospecha esto, utilice tar -tvfpara enumerar el contenido del archivo JAR sospechoso.

  5. Problemas de IDE : la gente ha informado de casos en los que su IDE se confunde y el compilador del IDE no puede encontrar una clase que exista... o la situación inversa.

    • Esto podría suceder si el IDE se configuró con la versión de JDK incorrecta.

    • Esto podría suceder si las cachés del IDE no están sincronizadas con el sistema de archivos. Hay formas específicas de IDE para solucionar este problema.

    • Esto podría ser un error de IDE. Por ejemplo, @Joel Costigliola describió un escenario en el que Eclipse no manejó correctamente un árbol de "prueba" de Maven: consulte esta respuesta . (Aparentemente, ese error en particular se solucionó hace mucho tiempo).

  6. Problemas de Android : cuando esté programando para Android y tenga errores de "No se puede encontrar el símbolo" relacionados con R, tenga en cuenta que los Rsímbolos están definidos por el context.xmlarchivo. Verifique que su context.xmlarchivo sea correcto y esté en el lugar correcto, y que el Rarchivo de clase correspondiente haya sido generado/compilado. Tenga en cuenta que los símbolos de Java distinguen entre mayúsculas y minúsculas, por lo que los identificadores XML correspondientes también distinguen entre mayúsculas y minúsculas.

    Es probable que otros errores de símbolos en Android se deban a los motivos mencionados anteriormente; por ejemplo, dependencias faltantes o incorrectas, nombres de paquetes incorrectos, métodos o campos que no existen en una versión de API en particular, errores ortográficos o tipográficos, etc.

  7. Ocultar clases del sistema : he visto casos en los que el compilador se queja de que substringes un símbolo desconocido en algo como lo siguiente

    String s = ...
    String s1 = s.substring(1);
    

    Resultó que el programador había creado su propia versión de Stringla clase y que su versión no definía ningún substringmétodo. He visto gente hacer esto con Systemy Scannerotras clases.

    Lección: ¡ No defina sus propias clases con los mismos nombres que las clases de biblioteca comunes!

    El problema también se puede resolver utilizando nombres completos. Por ejemplo, en el ejemplo anterior, el programador podría haber escrito:

    java.lang.String s = ...
    java.lang.String s1 = s.substring(1);
    
  8. Homoglifos: si utiliza codificación UTF-8 para sus archivos fuente, es posible tener identificadores que parecen iguales, pero que en realidad son diferentes porque contienen homoglifos. Vea esta pagina para mas informacion.

    Puede evitar esto limitándose a ASCII o Latin-1 como codificación del archivo fuente y utilizando \uxxxxescapes Java para otros caracteres.


1 - Si, por casualidad, ve esto en una excepción o mensaje de error en tiempo de ejecución, entonces ha configurado su IDE para ejecutar código con errores de compilación o su aplicación está generando y compilando código... en tiempo de ejecución.
2 - Los tres principios básicos de la ingeniería civil : el agua no corre cuesta arriba, una tabla es más fuerte de lado y no se puede empujar una cuerda .

Stephen C avatar Sep 07 '2014 01:09 Stephen C

También recibirás este error si olvidas un new:

String s = String();

versus

String s = new String();

porque la llamada sin la newpalabra clave intentará buscar un método (local) llamado Stringsin argumentos, y la firma del método probablemente no esté definida.

thinkterry avatar Apr 17 '2015 08:04 thinkterry

SOLUCIONADO

Usando IntelliJ

Seleccione Construir -> Reconstruir proyecto lo resolverá

Ajay avatar Oct 10 '2019 12:10 Ajay