Que signifie une erreur «Symbole introuvable» ou «Symbole impossible à résoudre»?

Sep 07 2014

Veuillez expliquer ce qui suit concernant les erreurs "Symbole introuvable", "Impossible de résoudre le symbole" ou "Symbole introuvable":

  • Que signifient-ils?
  • Quelles choses peuvent les provoquer?
  • Comment le programmeur s'y prend-il pour les corriger?

Cette question est conçue pour générer une période de questions-réponses complète sur ces erreurs de compilation courantes en Java.

Réponses

441 StephenC Sep 07 2014 at 08:12

0. Y a-t-il une différence entre les deux erreurs?

Pas vraiment. «Impossible de trouver le symbole», «Impossible de résoudre le symbole» et «Symbole non trouvé» signifient tous la même chose. Différents compilateurs Java utilisent une phraséologie différente.

1. Que signifie une erreur "Symbole introuvable"?

Premièrement, il s'agit d'une erreur de compilation 1 . Cela signifie soit qu'il y a un problème dans votre code source Java, soit qu'il y a un problème dans la façon dont vous le compilez.

Votre code source Java comprend les éléments suivants:

  • Mots - clés: comme true, false, class, whileet ainsi de suite.
  • Littéraux: comme 42et 'X'et "Hi mum!".
  • Les opérateurs et autres jetons non alphanumériques: comme +, =, {et ainsi de suite.
  • Identifiants: comme Reader, i, toString, processEquibalancedElephantset ainsi de suite.
  • Commentaires et espaces.

Une erreur "Symbole introuvable" concerne les identificateurs. Lorsque votre code est compilé, le compilateur doit déterminer ce que signifie chaque identificateur de votre code.

Une erreur «Symbole introuvable» signifie que le compilateur ne peut pas faire cela. Votre code semble faire référence à quelque chose que le compilateur ne comprend pas.

2. Qu'est-ce qui peut provoquer une erreur "Symbole introuvable"?

En premier lieu, il n'y a qu'une seule cause. Le compilateur a cherché dans tous les endroits où l'identifiant doit être défini, et il n'a pas pu trouver la définition. Cela peut être causé par un certain nombre de choses. Les plus courants sont les suivants:

  • Pour les identifiants en général:

    • Peut-être avez-vous mal orthographié le nom; c'est-à-dire StringBiulderau lieu de StringBuilder. Java ne peut pas et n'essaiera pas de compenser les fautes d'orthographe ou de frappe.
    • Peut-être avez-vous mal compris; c'est-à-dire stringBuilderau lieu de StringBuilder. Tous les identificateurs Java sont sensibles à la casse.
    • Peut-être avez-vous utilisé des traits de soulignement de manière inappropriée; c'est-à mystring- dire et my_stringsont différents. (Si vous vous en tenez aux règles de style Java, vous serez largement protégé de cette erreur ...)
    • Vous essayez peut-être d'utiliser quelque chose qui a été déclaré «ailleurs»; c'est-à-dire dans un contexte différent de celui où vous avez implicitement dit au compilateur de regarder. (Une classe différente? Une portée différente? Un package différent? Une base de code différente?)
  • Pour les identifiants qui doivent faire référence à des variables:

    • Vous avez peut-être oublié de déclarer la variable.
    • Peut-être que la déclaration de variable est hors de portée au moment où vous avez essayé de l'utiliser. (Voir l'exemple ci-dessous)
  • Pour les identificateurs qui doivent être des noms de méthode ou de champ:

    • Vous essayez peut-être de faire référence à une méthode ou un champ hérité qui n'a pas été déclaré dans les classes ou interfaces parent / ancêtre.

    • Vous essayez peut-être de faire référence à une méthode ou un champ qui n'existe pas (c'est-à-dire qui n'a pas été déclaré) dans le type que vous utilisez; par exemple "someString".push()2 .

    • Vous essayez peut-être d'utiliser une méthode comme champ, ou vice versa; par exemple "someString".lengthou someArray.length().

    • Peut-être que vous utilisez par erreur un tableau plutôt qu'un élément de tableau; par exemple

          String strings[] = ...
          if (strings.charAt(3)) { ... }
          // maybe that should be 'strings[0].charAt(3)'
      
  • Pour les identificateurs qui doivent être des noms de classe:

    • Vous avez peut-être oublié d'importer la classe.

    • Vous avez peut-être utilisé des importations "étoiles", mais la classe n'est définie dans aucun des packages que vous avez importés.

    • Peut-être avez-vous oublié un newcomme dans:

          String s = String();  // should be 'new String()'
      
  • Pour les cas où le type ou l'instance ne semble pas avoir le membre que vous attendiez:

    • Peut-être avez-vous déclaré une classe imbriquée ou un paramètre générique qui masque le type que vous vouliez utiliser.
    • Vous observez peut-être une variable statique ou d'instance.
    • Peut-être avez-vous importé le mauvais type; par exemple en raison de l'achèvement IDE ou de la correction automatique.
    • Peut-être que vous utilisez (compilez) la mauvaise version d'une API.
    • Peut-être avez-vous oublié de convertir votre objet dans une sous-classe appropriée.

Le problème est souvent une combinaison de ce qui précède. Par exemple, peut-être que vous "star" avez importé java.io.*et ensuite essayé d'utiliser la Filesclasse ... qui n'est java.niopas java.io. Ou peut-être que vous vouliez écrire File... ce qui est un cours java.io.


Voici un exemple de la façon dont une portée de variable incorrecte peut entraîner une erreur «Symbole introuvable»:

List<String> strings = ...

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

Cela donnera une erreur "Impossible de trouver le symbole" idans l' ifinstruction. Bien que nous ayons déclarée i, cette déclaration est que la portée de la fordéclaration et son corps. La référence à idans la ifdéclaration ne peut pas voir cette déclaration de i. C'est hors de portée .

(Une correction appropriée ici pourrait être de déplacer l' ifinstruction à l'intérieur de la boucle, ou de déclarer iavant le début de la boucle.)


Voici un exemple qui cause la perplexité où une faute de frappe conduit à une erreur apparemment inexplicable "Symbole introuvable":

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

Cela vous donnera une erreur de compilation dans l' printlnappel indiquant qu'il iest introuvable. Mais (je vous entends dire) je l'ai déclaré!

Le problème est le point-virgule sournois ( ;) avant le {. La syntaxe du langage Java définit un point-virgule dans ce contexte comme une instruction vide . L'instruction vide devient alors le corps de la forboucle. Donc, ce code signifie en fait ceci:

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

// The previous and following are separate statements!!

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

Le { ... }bloc n'est PAS le corps de la forboucle, et par conséquent, la déclaration précédente de idans l' forinstruction est hors de portée dans le bloc.


Voici un autre exemple d'erreur «Impossible de trouver le symbole» causée par une faute de frappe.

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

Malgré la déclaration précédente, le tmpdans l' tmp(...)expression est erroné. Le compilateur recherchera une méthode appelée tmpet n'en trouvera pas. Le précédemment déclaré se tmptrouve dans l'espace de noms des variables, pas dans l'espace de noms des méthodes.

Dans l'exemple que j'ai rencontré, le programmeur avait en fait omis un opérateur. Ce qu'il voulait écrire était ceci:

int res = tmp * (a + b);

Il y a une autre raison pour laquelle le compilateur peut ne pas trouver de symbole si vous compilez à partir de la ligne de commande. Vous avez peut-être simplement oublié de compiler ou de recompiler une autre classe. Par exemple, si vous avez des classes Fooet BarFooutilise Bar. Si vous n'avez jamais compilé Baret que vous exécutez javac Foo.java, vous risquez de constater que le compilateur ne trouve pas le symbole Bar. La réponse simple est de compiler Fooet Barensemble; par exemple javac Foo.java Bar.javaou javac *.java. Ou mieux encore, utilisez un outil de construction Java; par exemple Ant, Maven, Gradle et ainsi de suite.

Il y a aussi d'autres causes plus obscures ... que je traiterai ci-dessous.

3. Comment corriger ces erreurs?

De manière générale, vous commencez par déterminer ce qui a causé l'erreur de compilation.

  • Regardez la ligne dans le fichier indiquée par le message d'erreur de compilation.
  • Identifiez le symbole dont parle le message d'erreur.
  • Découvrez pourquoi le compilateur dit qu'il ne peut pas trouver le symbole; voir au dessus!

Ensuite, vous pensez à ce que votre code est censé dire. Enfin, vous déterminez la correction que vous devez apporter à votre code source pour faire ce que vous voulez.

Notez que toutes les «corrections» ne sont pas correctes. Considère ceci:

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

Supposons que le compilateur dise "Impossible de trouver le symbole" pour j. Il y a plusieurs façons de "corriger" ce problème:

  • Je pourrais changer l'intérieur foren for (int j = 1; j < 10; j++)- probablement correct.
  • Je pourrais ajouter une déclaration pour j avant la forboucle interne , ou la forboucle externe - peut-être correcte.
  • Je pouvais changer jà ila intérieur forboucle - probablement faux!
  • etc.

Le fait est que vous devez comprendre ce que votre code essaie de faire pour trouver le bon correctif.

4. Causes obscures

Voici quelques cas où le symbole "Impossible de trouver" est apparemment inexplicable ... jusqu'à ce que vous regardiez de plus près.

  1. Dépendances incorrectes : si vous utilisez un IDE ou un outil de génération qui gère le chemin de génération et les dépendances du projet, vous avez peut-être commis une erreur avec les dépendances; par exemple, omis une dépendance, ou sélectionné la mauvaise version. Si vous utilisez un outil de construction (Ant, Maven, Gradle, etc.), vérifiez le fichier de construction du projet. Si vous utilisez un IDE, vérifiez la configuration du chemin de génération du projet.

  2. Vous ne recompilez pas : il arrive parfois que les nouveaux programmeurs Java ne comprennent pas le fonctionnement de la chaîne d'outils Java, ou n'aient pas implémenté un «processus de construction» répétable; par exemple en utilisant un IDE, Ant, Maven, Gradle et ainsi de suite. Dans une telle situation, le programmeur peut finir par courir après sa queue à la recherche d'une erreur illusoire qui est en fait causée par une mauvaise recompilation du code, etc.

  3. Un problème de construction antérieure : il est possible qu'une version antérieure ait échoué d'une manière qui a donné un fichier JAR avec des classes manquantes. Un tel échec serait généralement remarqué si vous utilisiez un outil de construction. Cependant, si vous obtenez des fichiers JAR de quelqu'un d'autre, vous dépendez de leur construction correcte et de la détection des erreurs. Si vous suspectez cela, utilisez tar -tvfpour répertorier le contenu du fichier JAR suspect.

  4. Problèmes liés à l'IDE : des personnes ont signalé des cas où leur IDE est confus et le compilateur de l'EDI ne peut pas trouver une classe qui existe ... ou la situation inverse.

  • Cela peut se produire si l'EDI a été configuré avec la mauvaise version de JDK.

  • Cela peut se produire si les caches de l'EDI ne sont pas synchronisés avec le système de fichiers. Il existe des moyens spécifiques à l'IDE pour résoudre ce problème.

  • Cela pourrait être un bogue IDE. Par exemple, @Joel Costigliola décrit un scénario dans lequel Eclipse ne gère pas correctement un arbre "test" Maven: voir cette réponse .

  1. Problèmes Android : lorsque vous programmez pour Android et que vous rencontrez des erreurs «Symbole introuvable» R, sachez que les Rsymboles sont définis par le context.xmlfichier. Vérifiez que votre context.xmlfichier est correct et au bon endroit, et que le Rfichier de classe correspondant a été généré / compilé. Notez que les symboles Java sont sensibles à la casse, de sorte que les identifiants XML correspondants le sont également.

    D'autres erreurs de symboles sur Android sont probablement dues à des raisons mentionnées précédemment; par exemple, des dépendances manquantes ou incorrectes, des noms de package incorrects, une méthode ou des champs qui n'existent pas dans une version d'API particulière, des erreurs d'orthographe / de frappe, etc.

  2. Redéfinir les classes système : j'ai vu des cas où le compilateur se plaint qu'il substrings'agit d'un symbole inconnu dans quelque chose comme ce qui suit

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

    Il s'est avéré que le programmeur avait créé sa propre version de Stringet que sa version de la classe ne définissait pas de substringméthode.

    Leçon: Ne définissez pas vos propres classes avec les mêmes noms que les classes de bibliothèque courantes!

  3. Homoglyphes: Si vous utilisez l'encodage UTF-8 pour vos fichiers source, il est possible d'avoir des identifiants qui se ressemblent , mais qui sont en fait différents car ils contiennent des homoglyphes. Consultez cette page pour plus d'informations.

    Vous pouvez éviter cela en vous limitant à ASCII ou Latin-1 comme encodage du fichier source et en utilisant des \uxxxxéchappements Java pour les autres caractères.


1 - Si, par hasard, vous ne voyez cela à une exception d'exécution ou un message d'erreur, soit vous avez configuré votre IDE pour exécuter du code avec des erreurs de compilation, ou votre application génère et la compilation du code .. lors de l' exécution.

2 - Les trois principes de base du génie civil: l'eau ne coule pas en montée, une planche est plus solide de son côté et on ne peut pas pousser sur une ficelle .

26 thinkterry Apr 17 2015 at 15:50

Vous obtiendrez également cette erreur si vous oubliez un new:

String s = String();

contre

String s = new String();

car l'appel sans le newmot clé essaiera de rechercher une méthode (locale) appelée Stringsans arguments - et cette signature de méthode n'est probablement pas définie.

14 Jan Dec 06 2015 at 16:19

Un autre exemple de 'Variable est hors de portée'

Comme j'ai déjà vu ce genre de questions à quelques reprises, peut-être un autre exemple de ce qui est illégal, même si cela peut sembler correct.

Considérez ce code:

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

C'est un code invalide. Parce qu'aucune des variables nommées messagen'est visible en dehors de leur portée respective - qui seraient les crochets environnants {}dans ce cas.

Vous pourriez dire: "Mais une variable nommée message est définie de toute façon - donc le message est défini après le if".

Mais vous vous trompez.

Java n'a pas d' opérateurs free()ou delete, il doit donc s'appuyer sur la portée de la variable de suivi pour savoir quand les variables ne sont plus utilisées (avec des références à ces variables de cause).

C'est particulièrement mauvais si vous pensiez avoir fait quelque chose de bien. J'ai vu ce genre d'erreur après avoir "optimisé" le code comme ceci:

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

"Oh, il y a du code dupliqué, sortons cette ligne commune" -> et voilà.

La manière la plus courante de gérer ce type de problème de portée serait de pré-assigner les valeurs else aux noms de variable dans la portée extérieure, puis de les réaffecter si:

String message = "We have an error";
if(somethingIsTrue()) {
  message = "Everything is fine";
} 
System.out.println(message);
10 JoelCostigliola May 13 2016 at 17:09

Une façon d'obtenir cette erreur dans Eclipse:

  1. Définissez une classe Adans src/test/java.
  2. Définir une autre classe Bdans src/main/javacette classe utilisations A.

Résultat: Eclipse compilera le code, mais maven donnera "Impossible de trouver le symbole".

Cause sous-jacente: Eclipse utilise un chemin de construction combiné pour les arbres principal et de test. Malheureusement, il ne prend pas en charge l'utilisation de différents chemins de construction pour différentes parties d'un projet Eclipse, ce qui est requis par Maven.

Solution :

  1. Ne définissez pas vos dépendances de cette façon; c'est à dire ne faites pas cette erreur.
  2. Construisez régulièrement votre base de code à l'aide de Maven afin de détecter cette erreur tôt. Une façon de faire est d'utiliser un serveur CI.
5 GT_hash Jun 30 2018 at 18:09

"Impossible de trouver" signifie que, compilateur qui ne peut pas trouver la variable, la méthode, la classe appropriée, etc ... si vous avez ce massage d'erreur, vous voulez d'abord trouver la ligne de code où obtenir le massage d'erreur..Et ensuite capable de trouver quelle variable, méthode ou classe n'ont pas défini avant de l'utiliser.Après confirmation initialisez cette variable, méthode ou classe peut être utilisée pour plus tard ... Prenons l'exemple suivant.

Je vais créer une classe de démonstration et imprimer un nom ...

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

Regardez maintenant le résultat.

Cette erreur dit, "le nom de la variable ne peut pas être trouvé". La définition et l'initialisation de la valeur de la variable 'nom' peuvent être supprimées de cette erreur.

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

             String name="smith";

             System.out.print(name);
      }
}

Maintenant, regardez la nouvelle sortie ...

Ok. Cette erreur a été résolue avec succès..En même temps, si vous pouviez obtenir quelque chose "méthode introuvable" ou "classe introuvable", tout d'abord, définissez une classe ou une méthode et après utilisation.

3 JonathanLin Mar 08 2016 at 12:58

Si vous obtenez cette erreur dans la construction ailleurs, alors que votre IDE dit que tout va parfaitement bien, vérifiez que vous utilisez les mêmes versions de Java aux deux endroits.

Par exemple, Java 7 et Java 8 ont des API différentes, donc appeler une API inexistante dans une ancienne version de Java provoquerait cette erreur.

3 Ajay Oct 10 2019 at 19:07

RÉSOLU

Utilisation d'IntelliJ

Sélectionnez Build -> Rebuild Project le résoudra

2 DivyaJose Sep 28 2016 at 21:59

J'avais moi aussi cette erreur. (pour lequel j'ai googlé et j'ai été dirigé vers cette page)

Problème: j'appelais une méthode statique définie dans la classe d'un projet A à partir d'une classe définie dans un autre projet B.J'obtenais l'erreur suivante:

error: cannot find symbol

Solution: J'ai résolu ce problème en construisant d'abord le projet où la méthode est définie, puis le projet d'où la méthode a été appelée.

2 UdayKiranPulipati Jan 24 2019 at 18:18

Si le chemin de construction Java eclipse est mappé sur 7, 8 et dans le projet pom.xml Propriétés Maven java.version est mentionné une version Java supérieure (9,10,11, etc.,) à 7,8, vous devez mettre à jour dans pom. xml fichier.

Dans Eclipse, si Java est mappé sur Java version 11 et dans pom.xml, il est mappé sur Java version 8. Mettez à jour la prise en charge d'Eclipse vers Java 11 en suivant les étapes ci-dessous dans l'aide Eclipse IDE -> Installer un nouveau logiciel ->

Collez le lien suivant http://download.eclipse.org/eclipse/updates/4.9-P-builds at Work With

ou

Ajouter (la fenêtre contextuelle s'ouvre) ->

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

puis mettez à jour la version Java dans les propriétés Maven du fichier pom.xml comme ci-dessous

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

Enfin, faites un clic droit sur le projet Debug as -> Maven clean, Maven build steps

1 avp Aug 18 2018 at 08:45

Il peut y avoir différents scénarios comme les gens l'ont mentionné ci-dessus. Quelques éléments qui m'ont aidé à résoudre ce problème.

  1. Si vous utilisez IntelliJ

    File -> 'Invalidate Caches/Restart'

OU

  1. La classe référencée était dans un autre projet et cette dépendance n'a pas été ajoutée au fichier de construction Gradle de mon projet. J'ai donc ajouté la dépendance en utilisant

    compile project(':anotherProject')

et cela a fonctionné. HTH!

1 ANILKUMAR Aug 07 2019 at 11:59

vous avez compilé votre code en utilisant maven compile, puis vous avez utilisé le test maven pour l'exécuter. Maintenant, si vous avez modifié quelque chose dans votre code et que vous l'exécutez sans le compiler, vous obtiendrez cette erreur.

Solution: compilez-le à nouveau, puis exécutez le test. Pour moi, cela a fonctionné de cette façon.

1 VIPINKUMAR Sep 08 2019 at 14:50

Dans mon cas - j'ai dû effectuer les opérations ci-dessous:

  1. Déplacer le context.xmlfichier src/java/packagevers le resourcerépertoire (IntelliJ IDE)
  2. Nettoyer le targetrépertoire.
Striker Sep 06 2017 at 19:47

Pour obtenir des conseils, regardez de plus près le nom de la classe qui génère une erreur et le numéro de ligne, exemple: Échec de la compilation [ERREUR] \ applications \ xxxxx.java: erreur [44,30]: symbole introuvable

Une autre cause est une méthode non prise en charge pour la version java, disons jdk7 vs 8. Vérifiez votre% JAVA_HOME%

sakra Jul 20 2020 at 19:31

Nous avons eu l'erreur dans un projet Java configuré en tant que build multi-projets Gradle. Il s'est avéré que l'un des sous-projets manquait le plugin Gradle Java Library . Cela empêchait les fichiers de classe du sous-projet d'être visibles pour les autres projets de la construction.

Après avoir ajouté le plugin de bibliothèque Java aux sous-projets de build.gradlela manière suivante, l'erreur a disparu:

plugins {
    ...
    id 'java-library'
}
FelipeFranco Nov 20 2020 at 04:03

J'ai résolu cette erreur comme ça ... La folie d'Android. J'ai eu le nom du paquet comme adaptateur et j'ai refactorisé le nom en adaptateur avec un "a" au lieu de "A" et j'ai résolu l'erreur.