¿Qué significa el error "No se puede encontrar el símbolo" o "No se puede resolver el símbolo"?
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.
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
,while
etc. - Literales: como
true
,false
,42
y'X'
."Hi mum!"
- Operadores y otros tokens no alfanuméricos: como
+
,=
,{
etc. - Identificadores: como
Reader
,i
,toString
,processEquibalancedElephants
etc. - 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,
StringBiulder
en lugar deStringBuilder
. Java no puede ni intentará compensar los errores ortográficos o tipográficos. - Quizás se equivocó en el caso; es decir,
stringBuilder
en lugar deStringBuilder
. Todos los identificadores de Java distinguen entre mayúsculas y minúsculas. - Quizás usaste guiones bajos de manera inapropiada; es decir,
mystring
ymy_string
son 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?)
- Quizás hayas escrito mal el nombre; es decir,
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".length
osomeArray.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
new
como 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
package
van 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.List
en lugar dejava.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 Files
clase... que está en java.nio
not 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" i
en la if
declaración. Aunque anteriormente declaramos i
, esa declaración solo tiene alcance para 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 declararla i
antes 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 println
llamada que indica que i
no 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 for
bucle. 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 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, la tmp
expresión tmp(...)
es errónea. El compilador buscará un método llamado tmp
y no encontrará ninguno. Lo declarado previamente tmp
está 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 Foo
y Bar
dónde Foo
se usa Bar
. Si nunca ha compilado Bar
y ejecuta javac Foo.java
, es probable que descubra que el compilador no puede encontrar el símbolo Bar
. La respuesta simple es compilar Foo
y Bar
juntos; por ejemplo, javac Foo.java Bar.java
o 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
for
afor (int j = 1; j < 10; j++)
... probablemente correcto. - Podría agregar una declaración
j
antes del bucle internofor
o delfor
bucle externo, posiblemente correcta. - Podría cambiar
j
al buclei
internofor
, ¡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.
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.
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
var
declaración) con un compilador anterior o un--source
nivel anterior. Sevar
introdujo 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.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.java
para 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. Eljava
nuevo modo "compilar y ejecutar" del comando no está diseñado para ejecutar programas con múltiples archivos de código fuente.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 -tvf
para enumerar el contenido del archivo JAR sospechoso.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).
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 losR
símbolos están definidos por elcontext.xml
archivo. Verifique que sucontext.xml
archivo sea correcto y esté en el lugar correcto, y que elR
archivo 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.
Ocultar 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 siguienteString s = ... String s1 = s.substring(1);
Resultó que el programador había creado su propia versión de
String
la clase y que su versión no definía ningúnsubstring
método. He visto gente hacer esto conSystem
yScanner
otras 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);
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
\uxxxx
escapes 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 .
También recibirás este error si olvidas un new
:
String s = String();
versus
String s = new String();
porque la llamada sin la new
palabra clave intentará buscar un método (local) llamado String
sin argumentos, y la firma del método probablemente no esté definida.
SOLUCIONADO
Usando IntelliJ
Seleccione Construir -> Reconstruir proyecto lo resolverá