0. ¿Hay alguna diferencia entre los dos errores?
Realmente no. "No se puede encontrar el símbolo" y "No se puede resolver el símbolo" significan lo mismo. Algunos compiladores de Java usan una frase, y otros la otra.
1. ¿Qué significa el error "No se puede encontrar el símbolo"?
En primer lugar, es un error de compilación 1 . Esto significa que o bien hay un problema en el código fuente de Java, o hay un problema en la forma en que se está compilando.
Su código fuente Java consta de lo siguiente:
- Palabras clave: como
true
, false
, class
, while
, y así sucesivamente.
- Literales: como
42
y 'X'
y "Hi mum!"
.
- Los operadores y otros símbolos no alfanuméricos: como
+
, =
, {
, y así sucesivamente.
- Identificadores: como
Reader
, i
, toString
,processEquibalancedElephants
, y así sucesivamente.
- Comentarios y espacios en blanco.
El error "No se puede encontrar el símbolo" se refiere a los identificadores. Cuando se compila su código, el compilador necesita determinar qué significa cada identificador en su código.
Un error "No se puede encontrar el símbolo" significa que el compilador no puede hacer esto. Su código parece referirse a algo que el compilador no comprende.
2. ¿Qué puede causar el error "No se puede encontrar el símbolo"?
Como primer orden, solo hay una causa. El compilador buscó en todos los lugares donde se debería definir el identificador , y no pudo encontrar la definición. Esto podría ser causado por varias cosas. Los comunes son los siguientes:
- Para identificadores en general:
- Quizás deletreaste el nombre incorrectamente; es decir, en
StringBiulder
lugar de StringBuilder
. Java no puede y no intentará compensar los errores ortográficos o de escritura incorrectos.
- Quizás te equivocaste de caso; es decir, en
stringBuilder
lugar de StringBuilder
. Todos los identificadores de Java distinguen entre mayúsculas y minúsculas.
- Tal vez usaste guiones bajos inapropiadamente; es decir
mystring
y my_string
son diferentes. (Si te apegas a las reglas de estilo Java, estarás protegido en gran medida de este error ...)
- Quizás esté intentando usar algo que se declaró "en otro lugar"; es decir, en un contexto diferente al que implícitamente le ha dicho al compilador que busque. (¿Una clase diferente? ¿Un alcance diferente? ¿Un paquete diferente? ¿Una base de código diferente?)
- Para identificadores que deberían referirse a variables:
- Quizás olvidaste declarar la variable.
- Quizás la declaración de la variable está fuera del alcance en el punto en que trató de usarla. (Ver ejemplo a continuación)
Para identificadores que deberían ser nombres de método o campo:
Para identificadores que deberían ser nombres de clase:
Para los casos en que el tipo o la instancia no parecen tener el miembro que esperaba que tuviera:
- Tal vez ha declarado una clase anidada o un parámetro genérico que sombrea el tipo que quería usar.
- Quizás esté sombreando una variable estática o de instancia.
- Quizás importaste el tipo incorrecto; por ejemplo, debido a la finalización del IDE o la corrección automática
- Quizás esté utilizando (compilando) la versión incorrecta de una API.
- Quizás olvidó lanzar su objeto a una subclase apropiada.
El problema es a menudo una combinación de lo anterior. Por ejemplo, tal vez usted "destacó" importado java.io.*
y luego intentó usar la Files
clase ... que java.nio
no está java.io
. O tal vez quisiste escribir File
... que es una clase java.io
.
Aquí hay un ejemplo de cómo el alcance de variables incorrecto puede conducir a un 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 dará un error de "No se puede encontrar el símbolo" i
en la if
declaración. Aunque declaramos previamente i
, esa declaración solo está en el alcance de la for
declaración y su cuerpo. La referencia a i
en la if
declaración no puede ver esa declaración de i
. Está fuera de alcance .
(Una corrección apropiada aquí podría ser mover la if
declaración dentro del ciclo o declarar i
antes del inicio del ciclo).
Aquí hay un ejemplo que causa perplejidad donde un error tipográfico conduce a un error aparentemente inexplicable de "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 println
llamada diciendo que i
no se puede encontrar. Pero (te escucho decir) ¡lo dije!
El problema es el sigiloso punto y coma ( ;
) antes de {
. 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 en el cuerpo del for
bucle. Entonces ese código realmente 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 for
bucle y, por lo tanto, la declaración anterior de i
en la for
declaració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, el tmp
en la tmp(...)
expresión es erróneo. El compilador buscará un método llamado tmp
, y no encontrará uno. Lo declarado previamente tmp
está en el espacio de nombres para las variables, no en el espacio de nombres para los métodos.
En el ejemplo que encontré, el programador había dejado fuera a un operador. Lo que quiso escribir fue esto:
int res = tmp * (a + b);
Hay otra razón por la cual el compilador podría no encontrar un símbolo si está compilando desde la línea de comandos. Es posible que simplemente haya olvidado compilar o recompilar alguna otra clase. Por ejemplo, si usted tiene clases Foo
y Bar
donde Foo
los usos Bar
. Si nunca compiló Bar
y ejecuta javac Foo.java
, es probable que el compilador no pueda encontrar el símbolo Bar
. La respuesta simple es compilar Foo
y Bar
juntos; por ejemplo javac Foo.java Bar.java
ojavac *.java
. O mejor aún, use una herramienta de compilación Java; por ejemplo, Ant, Maven, Gradle, etc.
También hay otras causas más oscuras ... que trataré a continuación.
3. ¿Cómo soluciono estos errores?
En términos generales, comienza por descubrir qué causó el error de compilación.
- Mire la línea en el archivo indicado por el mensaje de error de compilación.
- Identifique de qué símbolo está hablando el mensaje de error.
- Averigüe por qué el compilador dice que no puede encontrar el símbolo; ¡véase más arriba!
Entonces piensas en lo que se supone que dice tu código. Luego, finalmente, determina qué corrección necesita hacer 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
for
a for (int j = 1; j < 10; j++)
- probablemente correcto.
- Podría agregar una declaración para
j
antes del for
bucle interno , o el externofor
, posiblemente correcta.
- Podría cambiar
j
a i
en el for
bucle interno , ¡probablemente incorrecto!
- y así.
El punto es que necesita comprender lo que su código está tratando de hacer para encontrar la solución correcta.
4. Causas oscuras
Aquí hay un par de casos en los que el "No se puede encontrar el símbolo" es aparentemente inexplicable ... hasta que mires más de cerca.
Dependencias incorrectas : si está utilizando un IDE o una herramienta de compilación que gestiona 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.
No está volviendo a compilar : 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 persiguiendo su cola en busca de un error ilusorio que en realidad es causado por no volver a compilar el código correctamente, y similares ...
Un problema de compilación anterior : es posible que una compilación anterior haya fallado de una manera que proporcionó un archivo JAR con clases faltantes. Tal falla normalmente se notaría si estuviera utilizando una herramienta de compilación. Sin embargo, si está obteniendo archivos JAR de otra persona, depende de que se construyan correctamente y noten errores. Si sospecha esto, use tar -tvf
para enumerar el contenido del archivo JAR sospechoso.
Problemas de IDE : las personas han informado casos en los que su IDE se confunde y el compilador en el IDE no puede encontrar una clase que exista ... o la situación inversa.
Esto podría suceder si el IDE se ha configurado con la versión 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 arreglar eso.
Esto podría ser un error IDE. Por ejemplo, @Joel Costigliola describe un escenario en el que Eclipse no maneja un árbol de "prueba" de Maven correctamente: vea esta respuesta .
Problemas de Android : cuando esté programando para Android y tenga errores relacionados con "No se pueden encontrar símbolos" R
, tenga en cuenta que los R
símbolos están definidos por el context.xml
archivo. Verifique que su context.xml
archivo sea correcto y esté en el lugar correcto, y que el R
archivo de clase correspondiente ha sido generado / compilado. Tenga en cuenta que los símbolos 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 razones mencionadas 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 de ortografía / escritura, etc.
Redefiniendo las clases del sistema : he visto casos en los que el compilador se queja de que substring
es 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 String
y que su versión de la clase no definía ningún substring
método.
Lección: ¡No defina sus propias clases con los mismos nombres que las clases de biblioteca comunes!
Homoglifos: si utiliza la codificación UTF-8 para sus archivos fuente, es posible tener identificadores que se vean iguales, pero de hecho son diferentes porque contienen homoglifos. Vea esta página para más información.
Puede evitar esto restringiéndose a ASCII o Latin-1 como codificación del archivo fuente, y utilizando \uxxxx
escapes de Java para otros caracteres.
1 - Si, por ventura, que qué ver esto en una excepción de tiempo de ejecución o mensaje de error, ya sea que haya configurado el IDE para ejecutar código con errores de compilación, o su aplicación es la generación y compilación de código .. en tiempo de ejecución.
2 - Los tres principios básicos de la Ingeniería Civil: el agua no fluye cuesta arriba, un tablón es más fuerte de lado y no se puede empujar una cuerda .