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

395

Explique lo siguiente sobre los errores "No se puede encontrar el símbolo" y "No se puede resolver el símbolo":

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

Esta pregunta está diseñada para generar un Q&A completo sobre estos errores comunes de compilación en Java.

Stephen C
fuente

Respuestas:

417

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 42y '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 StringBiulderlugar 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 stringBuilderlugar de StringBuilder. Todos los identificadores de Java distinguen entre mayúsculas y minúsculas.
    • Tal vez usaste guiones bajos inapropiadamente; es decir mystringy my_stringson 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:

    • Quizás esté intentando hacer referencia a un método o campo heredado que no se declaró en las clases o interfaces principales / ancestrales.
    • Quizás esté intentando referirse a un método o campo que no existe (es decir, no ha sido declarado) en el tipo que está utilizando; por ejemplo "someString".push()2 .
    • Quizás esté intentando utilizar un método como campo, o viceversa; por ejemplo "someString".lengtho someArray.length().
    • Quizás esté operando por error en una matriz en lugar de un elemento de 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 clase:

    • Quizás olvidaste 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()'
  • 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 Filesclase ... que java.niono 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" ien la ifdeclaración. Aunque declaramos previamente i, esa declaración solo está en el alcance de 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 declarar iantes 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 printlnllamada diciendo que ino 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 forbucle. 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 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, el tmpen la tmp(...)expresión es erróneo. El compilador buscará un método llamado tmp, y no encontrará uno. Lo declarado previamente tmpestá 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 Fooy Bardonde Foolos usos Bar. Si nunca compiló Bary ejecuta javac Foo.java, es probable que el compilador no pueda encontrar el símbolo Bar. La respuesta simple es compilar Fooy Barjuntos; por ejemplo javac Foo.java Bar.javaojavac *.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 fora for (int j = 1; j < 10; j++)- probablemente correcto.
  • Podría agregar una declaración para j antes del forbucle interno , o el externofor , posiblemente correcta.
  • Podría cambiar ja ien el forbucle 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.

  1. 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.

  2. 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 ...

  3. 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 -tvfpara enumerar el contenido del archivo JAR sospechoso.

  4. 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 .

  5. 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 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 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.

  6. Redefiniendo las 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 Stringy que su versión de la clase no definía ningún substringmétodo.

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

  7. 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 \uxxxxescapes 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 .

Stephen C
fuente
Tuve otra situación en la que se produjo este error de compilación mientras que eclipse no vio el problema: dos clases con dependencias definidas en la otra clase respectivamente. En mi caso, tenía una enumeración, implementando una interfaz, definida en una clase donde tontamente ya usaba la enumeración.
Jogi
Algo similar al comentario anterior, cuando compilo y ejecuto mi programa desde Eclipse, no funciona ningún problema. Compilarlo desde la consola genera un montón de estos errores "No se puede encontrar el símbolo" a menudo relacionados con el último elemento en una importación. No tengo idea de qué está causando esto, ya que no hay nada malo en el código realmente.
Andres Stadelmann
Otro problema es que los IDE pueden "interpretar" otros errores en esta categoría. Por ejemplo println, en System.out.printlnsi se coloca a nivel de clases bajo el compilador estándar nos daría <identifier> expected( Demo ) pero en IntelliJ veremos Cannot resolve symbol 'println'( Demo ).
Pshemo
Guau. Yo llamaría a eso un error del compilador.
Stephen C
23

También recibirá este error si olvida 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 es probable que la firma del método no esté definida.

pensamiento
fuente
14

Un ejemplo más de 'La variable está fuera de alcance'

Como ya he visto ese tipo de preguntas varias veces, tal vez un ejemplo más de lo que es ilegal, incluso si se siente bien.

Considera este código:

if(somethingIsTrue()) {
  String message = "Everything is fine";
} else {
  String message = "We have an error";
}
System.out.println(message);

Ese es un código inválido. Porque ninguna de las variables nombradas messagees visible fuera de su ámbito respectivo, que serían los corchetes circundantes {}en este caso.

Podría decir: "Pero una variable llamada mensaje se define de cualquier manera, por lo que el mensaje se define después de if".

Pero te equivocarías.

Java no tiene free()o deletelos operadores, por lo que tiene que confiar en el seguimiento de alcance variable para averiguar cuándo las variables ya no se utilizan (junto con referencias a estas variables de la causa).

Es especialmente malo si crees que hiciste algo bueno. He visto este tipo de error después de "optimizar" un código como este:

if(somethingIsTrue()) {
  String message = "Everything is fine";
  System.out.println(message);
} else {
  String message = "We have an error";
  System.out.println(message);
}

"Oh, hay código duplicado, saquemos esa línea común" -> y ahí está.

La forma más común de lidiar con este tipo de problemas de alcance sería preasignar los valores else a los nombres de las variables en el alcance externo y luego reasignarlos si:

String message = "We have an error";
if(somethingIsTrue()) {
  message = "Everything is fine";
} 
System.out.println(message);
ene
fuente
44
"Java no tiene operadores libres () o de eliminación, por lo que debe basarse en el alcance de la variable de seguimiento para averiguar cuándo las variables ya no se usan (junto con las referencias a estas variables de causa)". - Si bien es cierto, esto no es relevante. C y C ++ tienen operadores libres / eliminar respectivamente, y sin embargo, el código C / C ++ equivalente a sus ejemplos sería ilegal. Los bloques C y C ++ limitan el alcance de las variables al igual que en Java. De hecho, esto es cierto para la mayoría de los lenguajes "estructurados en bloque".
Stephen C
1
La mejor solución para el código que asigna un valor diferente en cada rama es usar una declaración de variable en blancofinal .
Daniel Pryden
10

Una forma de obtener este error en Eclipse:

  1. Definir una clase Aen src/test/java.
  2. Defina otra clase Ben src/main/javaque use la clase A.

Resultado: Eclipse compilará el código, pero Maven dará "No se puede encontrar el símbolo".

Causa subyacente: Eclipse está utilizando una ruta de compilación combinada para los árboles principal y de prueba. Desafortunadamente, no admite el uso de diferentes rutas de compilación para diferentes partes de un proyecto Eclipse, que es lo que requiere Maven.

Solución:

  1. No defina sus dependencias de esa manera; es decir, no cometas este error.
  2. Cree regularmente su base de código utilizando Maven para que pueda detectar este error antes de tiempo. Una forma de hacerlo es usar un servidor CI.
Joel Costigliola
fuente
¿Cuál es la solución a este?
2
lo que use en src / main / java debe definirse en src / main / java o en cualquier dependencia de compilación / tiempo de ejecución (no dependencias de prueba).
Joel Costigliola
5

"No se puede encontrar" significa que, el compilador que no puede encontrar la variable, el método, la clase, etc. adecuados, si recibió ese error de masaje, en primer lugar, desea encontrar la línea de código donde obtener el error de masaje ... Y luego lo hará capaz de encontrar qué variable, método o clase no ha definido antes de usarlo. Después de la confirmación, inicialice que la variable, método o clase puede usarse para luego requerir ... Considere el siguiente ejemplo.

Crearé una clase de demostración e imprimiré un nombre ...

class demo{ 
      public static void main(String a[]){
             System.out.print(name);
      }
}

Ahora mira el resultado ...

ingrese la descripción de la imagen aquí

Ese error dice, "el nombre de la variable no puede encontrar". Definir e inicializar el valor para la variable 'nombre' puede ser eliminado ese error ... En realidad así,

class demo{ 
      public static void main(String a[]){

             String name="smith";

             System.out.print(name);
      }
}

Ahora mira la nueva salida ...

ingrese la descripción de la imagen aquí

Ok Resuelto con éxito ese error ... Al mismo tiempo, si pudieras obtener algo "no se puede encontrar el método" o "no se puede encontrar la clase", Al principio, define una clase o método y después de usarlo ...

GT_hash
fuente
3

Si obtiene este error en la compilación en otro lugar, mientras su IDE dice que todo está perfectamente bien, compruebe que esté utilizando las mismas versiones de Java en ambos lugares.

Por ejemplo, Java 7 y Java 8 tienen API diferentes, por lo que llamar a una API inexistente en una versión anterior de Java causaría este error.

Jonathan Lin
fuente
2

Yo también recibí este error. (para lo cual busqué en Google y fui dirigido a esta página)

Problema: estaba llamando a un método estático definido en la clase de un proyecto A desde una clase definida en otro proyecto B. Recibía el siguiente error:

error: cannot find symbol

Solución: Resolví esto construyendo primero el proyecto donde se define el método y luego el proyecto desde donde se llamó al método.

Divya Jose
fuente
Sí, esto puede suceder si decide mover alguna función reutilizable de su paquete actual a su paquete de utilidades comunes, por ejemplo, pero luego olvida compilar su paquete común antes de llamar a la función desde su paquete actual.
buildingKofi
2

Si la ruta de compilación Java de eclipse está asignada a 7, 8 y en el Proyecto pom.xml Propiedades de Maven, java.version menciona una versión de Java más alta (9,10,11, etc.) que 7,8 que necesita actualizar en pom. archivo xml

En Eclipse si Java está asignado a Java versión 11 y en pom.xml está asignado a Java versión 8. Actualice el soporte de Eclipse a Java 11 siguiendo los pasos a continuación en la Ayuda de eclipse IDE -> Instalar nuevo software ->

Pegue el siguiente enlace http://download.eclipse.org/eclipse/updates/4.9-P-builds at Work With

o

Agregar (se abrirá una ventana emergente) ->

Name:Soporte de Java 11 Location: http://download.eclipse.org/eclipse/updates/4.9-P-builds

luego actualice la versión de Java en las propiedades Maven del archivo pom.xml como se muestra a continuación

<java.version>11</java.version>
<maven.compiler.source>${java.version}</maven.compiler.source>
<maven.compiler.target>${java.version}</maven.compiler.target>

Finalmente, haga clic derecho en la depuración del proyecto como -> Maven clean, Maven build steps

UdayKiran Pulipati
fuente
2

RESUELTO

Seleccione Build -> Rebuild Project lo resolverá

Ajay
fuente
1
Eso depende mucho y generalmente no.
Maarten Bodewes
1

Puede haber varios escenarios como la gente ha mencionado anteriormente. Un par de cosas que me han ayudado a resolver esto.

  1. Si está utilizando IntelliJ

    File -> 'Invalidate Caches/Restart'

O

  1. La clase a la que se hace referencia estaba en otro proyecto y esa dependencia no se agregó al archivo de compilación de Gradle de mi proyecto. Entonces agregué la dependencia usando

    compile project(':anotherProject')

Y funcionó. HTH!

avp
fuente
1

compiló su código usando compilación maven y luego usó la prueba maven para ejecutarlo funcionó bien. Ahora, si cambió algo en su código y luego, sin compilarlo, lo está ejecutando, obtendrá este error.

Solución: compílelo nuevamente y luego ejecute la prueba. Para mí funcionó de esta manera.

ANIL KUMAR
fuente
1

En mi caso, tuve que realizar las siguientes operaciones:

  1. Mover context.xmlarchivo desde src/java/packageal resourcedirectorio (IntelliJ IDE)
  2. targetDirectorio limpio
VIPIN KUMAR
fuente
Mover el archivo sin preocuparse por las referencias puede causar este error. Ya conocí esto. Simplemente reinicie en Git y mueva cuidadosamente nuevamente, el error se resolverá.
Huy Hóm Hỉnh
0

Para obtener sugerencias, observe más de cerca el nombre del nombre de la clase que arroja un error y el número de línea, por ejemplo: Error de compilación [ERROR] \ aplicaciones \ xxxxx.java: [44,30] error: no se puede encontrar el símbolo

Otra causa es el método no compatible de la versión de Java, por ejemplo, jdk7 vs 8. Compruebe su% JAVA_HOME%

Huelguista
fuente
Esto solo dice lo mismo que dicen otras respuestas.
Stephen C