Java >> Tutoriel Java >  >> Java

L'erreur de compilation "Impossible de trouver le symbole" en Java

Lorsqu'un utilisateur fait référence à une variable qui n'a pas été déclarée dans l'application, l'erreur "symbole introuvable" se produit. Autrement dit, le compilateur n'est pas conscient de la déclaration de la variable. Par exemple :

class HelloCodeunderscored {
    public static void main( String args[] ) {
      int x = 15;
      int y =1 4;
      // result is not declared. It will show an error.
      result = x * y;
    }
}

Quelles sont les solutions possibles à ce problème ?

Si jamais vous rencontrez ce problème, vous devriez revoir le code pour les scénarios suivants :

  • Assurez-vous d'avoir déclaré la variable, par exemple, int i =15;. Si int n'a pas été écrit, l'erreur peut s'afficher.
  • Vérifiez également si la variable définie est en dehors du code, par exemple, si elle n'est pas membre de la classe HelloCodeunderscored.
  • Assurez-vous d'utiliser la bonne coque. Si vous déclarez une variable en tant que var mais que vous y accédez en tant que Var, c'est un exemple d'un tel scénario.
  • Les chiffres, les signes dollar et les traits d'union ne sont pas autorisés dans les valeurs d'identifiant ; vérifiez-les.

Erreurs de temps de compilation

Le compilateur examine et vérifie le code pour diverses choses lors de la compilation, y compris les types de référence, les conversions de type et les déclarations de méthode, pour n'en citer que quelques-uns. Cette étape du processus de compilation est cruciale car c'est ici que nous rencontrerons une erreur de compilation.

Les erreurs de compilation peuvent être divisées en trois catégories :

Erreurs de syntaxe

L'une des erreurs de programmation les plus courantes consiste à ne pas utiliser de point-virgule à la fin d'une instruction ; d'autres erreurs typiques incluent l'oubli des importations, les parenthèses qui ne correspondent pas et l'omission de l'instruction de retour.

Erreurs de vérification de type

C'est une méthode pour s'assurer que notre code est de type sûr. Avec cette vérification, nous fournissons que les types d'expressions sont cohérents. Si nous définissons une variable de type int, nous ne devons jamais lui attribuer une valeur de type double ou String.

Le compilateur va planter

Pendant ce temps, il y a une chance que le compilateur plante. C'est exceptionnellement rare, mais ça arrive. Dans ce scénario, il est bon de savoir que le problème ne vient pas de notre code mais d'autre chose.

Les compilateurs suivent un ensemble de règles spécifiques à chaque langage. Si un code ne respecte pas ces exigences, le compilateur ne pourra pas le convertir, ce qui entraînera une erreur de compilation. La clé pour résoudre le problème de compilation "Impossible de trouver le symbole" est de comprendre ce qui le cause.

Nous pouvons déduire la ligne de code où le problème s'est produit et quel élément est incorrect du message d'erreur. Connaître les causes les plus courantes de cette erreur facilitera et accélérera sa résolution.

Tableaux de symboles :un aperçu

Les compilateurs construisent et maintiennent des tables de symboles, qui sont des structures de données importantes pour stocker des informations relatives aux identifiants dans le code source. Ces informations sont placées dans des tables de symboles lors de l'analyse lexicale et syntaxique, puis utilisées dans le processus de compilation.

Les identificateurs des classes, des interfaces, des variables et des méthodes sont liés pour correspondre aux entrées dans les tables de symboles lorsque les déclarations sont traitées. Lorsque ces identifiants apparaissent dans le code source, le compilateur les recherche dans les tables de symboles. Il utilise ces informations pour confirmer qu'une variable a été déclarée, établir la portée de la variable et effectuer une vérification de type pour s'assurer qu'une expression est sémantiquement correcte.

Les tables de symboles sont également utilisées dans la création et l'optimisation du code. Voici une représentation simplifiée d'une entrée de table de symboles (ou simplement d'un symbole) en Java :

<symbol name (identifier), type, scope, [attributes]>

La notation comparable pour une déclaration de variable globale, telle que le double ratio final, serait .

Erreur :Impossible de trouver le symbole

Comme son nom l'indique, l'erreur Impossible de localiser le symbole fait référence à un symbole que vous ne pouvez pas trouver. Bien qu'il existe diverses causes à cela, elles se résument toutes à l'incapacité du compilateur Java à localiser le symbole associé à un identifiant donné.

Deux autres champs sont inclus dans le message du compilateur pour l'erreur Impossible de localiser le symbole :

"symbole" fait référence au nom et au type de l'identifiant référencé. D'autre part, "emplacement" fait référence à la classe où l'identifiant est utilisé.

Qu'est-ce qui cause l'erreur symbole introuvable ?

Voici les causes les plus courantes de l'erreur Impossible de localiser le symbole au moment de la compilation :

  • Déclarations de variables et de méthodes manquantes,
  • Références à des variables et méthodes hors champ d'application
  • identifiants mal orthographiés, et
  • instructions d'importation omises.

Symbole introuvable vs. Impossible de trouver le symbole vs. Impossible de résoudre le symbole

Le problème de symbole introuvable peut également être rencontré sous les mots symbole introuvable et symbole impossible à résoudre, car différents compilateurs Java utilisent une formulation quelque peu différente. Hormis les noms, il n'y a aucune différence entre les significations de ces phrases.

Exemples de "Impossible de trouver l'erreur de symbole."

Certaines de ces "erreurs de symboles introuvables" sont les suivantes :

Gérer une variable non déclarée

L'erreur Impossible de trouver le symbole est déclenchée lorsque le compilateur Java rencontre un identifiant qu'il ne peut pas trouver dans la table des symboles. Par conséquent, la cause la plus courante de cette erreur est lorsqu'une référence à une variable non déclarée est faite. Contrairement à certains autres langages, qui ne nécessitent pas de déclarations de variables explicites ou peuvent permettre de déclarer une variable après qu'elle a été référencée (par levage), Java exige qu'une variable soit déclarée avant d'être utilisée ou référencée sous quelque forme que ce soit.

La figure (a) montre comment une variable non déclarée, dans ce cas, la moyenne de l'identifiant sur la ligne 9, provoque deux instances de l'erreur de symbole introuvable aux emplacements du code. La figure (b) résout le problème en déclarant cette variable avec son type de données (ou en déduisant son genre avec le mot-clé var dans Java 10+).

Figure (a)

package codeunderscored;

public class CodeUndeclaredVariable {
    public static void main(String... args) {
        int x = 16;
        int y = 20;
        int z = 42;

        averageResults = (x + y + z) / 3.0; // averageResults is not declared
        System.out.println(averageResults);
    }
}

Figure (b)

package codeunderscored;

public class UndeclaredVariable {
    public static void main(String... args) {
        int x = 16;
        int y = 20;
        int z = 42;

        double averageResults = (x + y + z) / 3.0;
        System.out.println(averageResults);
    }
}

Traitement d'une variable hors champ

Le compilateur génère l'erreur Impossible de trouver le symbole lorsqu'une application Java tente d'accéder à une variable déclarée dans une portée distincte (non héritée ou sans chevauchement). L'effort pour essayer d'avoir accès au compteur de variables sur les lignes 17 et 18 de la figure (a), qui n'est disponible que dans l'instruction déclarée sur la ligne 11, le démontre. La figure (b) indique que le déplacement de la variable compteur en dehors de la boucle for résout le problème.

Figure (a)

package codeunderscored;

import java.util.Arrays;
import java.util.List;

public class CodeOutOfScopeVariable {
    public static void main(String... args) {
        final List<String> strings = Arrays.asList("Hello", "Codeunderscored");
        final String searchFor = "Codeunderscored";

        for (int counter = 0; counter < strings.size(); counter++) {
            if (strings.get(counter).equals(searchFor)) {
                break;
            }
        }

        if (counter < strings.size()) {
            System.out.println("The word " + searchFor + " was found at index " +    counter);
        } else {
            System.out.println("The word " + searchFor + " wasn't found");
        }
    }
}

Figure (b)

package codeunderscored;

import java.util.Arrays;
import java.util.List;

public class CodeOutOfScopeVariable {
    public static void main(String... args) {
        final List<String> strings = Arrays.asList("Hello", "Codeunderscored");
        final String searchFor = "Codeunderscored";
        int counter;

        for (counter = 0; counter < strings.size(); counter++) {
            if (strings.get(counter).equals(searchFor)) {
                break;
            }
        }

        if (counter < strings.size()) {
            System.out.println("The word " + searchFor + " was found at index " + counter);
        } else {
            System.out.println("The word " + searchFor + " wasn't found");
        }
    }
}

Figures (a) &(b) :Erreur et résolution pour ne pas avoir pu découvrir un symbole pour une variable hors champ.

Nom de la méthode mal orthographié

Une erreur Impossible de localiser le symbole est causée par une mauvaise orthographe d'une méthode existante ou de tout identifiant valide. Étant donné que les identifiants Java sont sensibles à la casse, toute modification d'une variable, d'une méthode, d'une classe, d'une interface ou d'un nom de package existant, comme illustré à la figure (b), entraînera cette erreur.

Figure (a)

package codeunderscored;

public class CodeMisspelledMethodName {

    static int fibonacci(int n) {
        if (n == 0) return 0;
        if (n == 1) return 1;
        return fibonacci(n - 1) + fibonacci(n - 2);
    }

    public static void main(String... args) {
        int fibResult = Fibonacci(20); // Fibonacci ≠ fibonacci
        System.out.println(fibResult);
    }
}

Figure (b)

package codeunderscored;

public class CodeMisspelledMethodName {
    static int fibonacci(int n) {
        if (n == 0) return 0;
        if (n == 1) return 1;
        return fibonacci(n - 1) + fibonacci(n - 2);
    }

    public static void main(String... args) {
        int fibResult = fibonacci(20);
        System.out.println(fibResult);
    }
}

Figure d'erreur (a) et figure de résolution (b) :Impossible de trouver le symbole d'un nom de méthode mal orthographié

Une déclaration d'importation est manquante

L'utilisation de classes, qu'elles proviennent de la plate-forme Java ou d'une bibliothèque, nécessite de les importer de manière appropriée à l'aide de l'instruction import. Si vous ne le faites pas, le compilateur Java se plaindra d'un symbole introuvable. Le package java.util est utilisé dans l'exemple de code de la figure (a). Le problème de l'impossibilité de localiser le symbole survient car la classe de liste a été créée sans spécifier l'importation nécessaire. Le problème est résolu en ajoutant la ligne 4 de l'instruction d'importation manquante dans la figure (b).

Figure (a)

package codeunderscored;

import java.util.Arrays;

public class CodeMissingImportList {
    private static final List<String> CONSTANTS = Arrays.asList("A", "B", "C");

    public static void main(String... args) {
        System.out.println(CONSTANTS);
    }
}

Figure (b)

package codeunderscored;

import java.util.Arrays;
import java.util.List;

public class CodeMissingImportList {
    private static final List<String> CONSTANTS = Arrays.asList("A", "B", "C");

    public static void main(String... args) {
        System.out.println(CONSTANTS);
    }
}

Figure (a) Erreur et résolution (b) :Impossible de trouver le symbole de l'importation manquante

Exemples moins courants

La cause fondamentale de l'erreur Java ne peut pas localiser le symbole se trouve parfois dans des zones inattendues ou cachées. C'est le cas lorsqu'une phrase se termine prématurément par un point-virgule involontaire Figure (a) ou lorsque la création d'un objet est tentée sans invocation correcte du constructeur, qui doit inclure le nouveau mot-clé Figure 6.

Figure (a)

package codeunderscored;

public class CodeLoopScope {

public static void main(String... args) {
        int start = 1, end = 10;
        for (int i = start; i <= end; i++); {
            System.out.print(i == end ? i : i + ", ");
        }
    }
}

Figure (b)

package codeunderscored;

public class CodeLoopScope {
    public static void main(String... args) {
        int start = 1, end = 10;
        for (int i = start; i <= end; i++) {
            System.out.print(i == end ? i : i + ", ");
        }
    }
}

Impossible de localiser un symbole pour une boucle arrêtée prématurément Erreur de la figure (a) et résolution de la figure (b)

Figure (a)

package codeunderscored;

public class CodeObjectCreation {
    public static void main(String... args) {
        String s = String("Hello Codeunderscored!");
        System.out.println(s);
    }
}

Figure (b)

package codeunderscored;

public class CodeObjectCreation {
    public static void main(String... args) {
        String s = new String("Hello Codeunderscored!");
        System.out.println(s);
    }
}

Figure (a) Erreur et figure (b) Résolution pour Impossible de trouver l'appel du constructeur de symboles

Les autres raisons du problème "symbole introuvable" incluent :

Voici quelques cas où le "Impossible de détecter le symbole" semble inexplicable jusqu'à ce que vous approfondissiez vos recherches.

Impossible de trouver le symbole "var" :

Vous essayez probablement de compiler le code source avec un compilateur plus ancien ou un niveau de source plus ancien qui utilise l'inférence de type de variable locale (c'est-à-dire une déclaration var). Dans Java 10, le var a été introduit. Vérifiez votre version de JDK, les fichiers de construction et les paramètres de l'IDE (si cela se produit dans un IDE).

Vous ne compilez ou ne recompilez rien

Les nouveaux programmeurs Java ne comprennent parfois pas le fonctionnement de la chaîne d'outils Java ou n'ont pas mis en place un "processus de construction" reproductible, tel que l'utilisation d'un IDE, Ant, Maven, Gradle, etc. Dans ce cas, le programmeur peut finir par chasser sa queue, à la recherche d'un défaut imaginaire causé par une recompilation incorrecte du code, etc.

Un autre exemple est lorsque vous compilez et exécutez une classe avec (Java 9+) java SomeClass.java. Vous risquez d'obtenir des erreurs "Impossible de résoudre le symbole" faisant référence à la 2ème classe si la classe dépend d'une autre classe que vous n'avez pas compilée (ou recompilée). Les autres fichiers source ne sont pas compilés automatiquement. De plus, le nouveau mode "compiler et exécuter" de la commande java n'est pas adapté au lancement de programmes avec plusieurs fichiers de code source.

Dépendances incorrectes

Si vous utilisez un IDE ou un outil de build qui gère le chemin de build et les dépendances du projet, vous avez peut-être fait une erreur avec les dépendances; par exemple, vous avez peut-être omis une dépendance ou choisi la mauvaise version. Vérifiez le fichier de construction du projet si vous utilisez un outil de construction (Ant, Maven, Gradle, etc.). De plus, examinez la configuration du chemin de construction du projet si vous utilisez un IDE.

Un problème avec une version précédente

Il est possible qu'une version précédente ait échoué, donc un fichier JAR a été créé avec des classes manquantes. Vous remarquerez généralement un tel échec si vous utilisiez un outil de construction. Si vous acquérez des fichiers JAR de quelqu'un d'autre, vous devrez compter sur eux pour construire correctement et détecter les erreurs.

Utilisez tar -tvf lorsque vous devez répertorier le contenu des fichiers JAR suspects si vous le soupçonnez.

Problèmes avec Android

Lorsque vous programmez pour Android et que vous rencontrez des problèmes "Impossible de découvrir le symbole" liés à R, gardez à l'esprit que le fichier context.xml définit les symboles R. Vérifiez que votre fichier context.xml est valide et au bon emplacement et que le fichier de classe R correspondant a été généré et compilé. Comme les symboles Java sont sensibles à la casse, les identifiants XML correspondants le sont également.

D'autres problèmes de symboles sur Android sont le plus souvent causés par les facteurs mentionnés ci-dessus, tels que des dépendances manquantes ou inexactes, des noms de packages incorrects, des méthodes ou des champs qui n'existent pas dans une version d'API spécifique, des problèmes d'orthographe/de frappe, etc. /P>

Problèmes avec l'IDE

Les gens ont signalé des occasions où leur IDE devient confus, et le compilateur de l'IDE ne peut pas détecter une classe qui existe déjà… ou vice versa. Si l'IDE est configuré avec la mauvaise version du JDK, cela peut arriver.

Si les caches de l'IDE ne sont plus synchronisés avec le système de fichiers, cela peut arriver.

Il existe des solutions spécifiques à l'IDE pour cela. Ce dernier pourrait être un problème dans l'IDE. Par exemple, il y a un cas typique de la façon dont Eclipse a mal géré un arbre de "test" Maven. Ce bogue particulier, semble-t-il, a été corrigé il y a longtemps.

Homoglyphes

Il est possible d'avoir des identifiants qui semblent identiques mais qui ne le sont pas parce qu'ils contiennent des homoglyphes si vous utilisez l'encodage UTF-8 pour vos fichiers source. Vous pouvez contourner ce problème en limitant l'encodage du fichier source à ASCII ou Latin-1 et en utilisant les échappements Java \uxxxx pour les caractères supplémentaires.

Classes de système caché

Nous avons vu des situations où le compilateur se plaint que la sous-chaîne est un symbole inconnu, comme celui-ci.

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

Il s'avère que le programmeur avait écrit sa version de String, qui manquait d'opérations de sous-chaînes. Cela a été fait avec System, Scanner et d'autres classes dans le passé.

Dans l'ensemble, n'utilisez pas les mêmes noms que les classes de bibliothèque courantes lors de la définition de vos classes ! Vous pouvez également utiliser des noms complets pour remédier à la situation. Dans l'exemple précédent, le programmeur peut avoir écrit :

java.lang.String s = ...

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

Que dois-je faire à propos de ces erreurs ?

  • En général, vous devez commencer par déterminer ce qui a déclenché l'erreur de compilation.
  • Examinez la ligne du fichier à laquelle l'avis d'erreur de compilation fait référence.
  • Déterminez à quel symbole le message d'erreur fait référence.
  • Comprendre pourquoi le compilateur dit qu'il ne peut pas trouver le symbole ; consultez la section ci-dessus !
  • Ensuite, vous considérez ce que votre code essaie de communiquer.
  • Ensuite, essayez de déterminer les modifications que vous devez apporter à votre code source pour qu'il fasse ce que vous voulez.

Il convient de noter que toutes les "corrections" ne sont pas exactes. Considérez ce qui suit :

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

Supposons que le compilateur indique pour j, "Impossible de trouver le symbole". Il existe plusieurs façons de "corriger" cela :

  • Nous supposons que nous pourrions modifier le for intérieur en for (int j =1 ; j<10 ; j++) – ce qui serait correct.
  • Alternativement, nous pourrions mettre une déclaration pour j avant les boucles for internes ou externes, ce qui serait probablement correct.
  • Dans la boucle for interne, nous pourrions également changer j en i, et ce serait incorrect ! et ainsi de suite. Pour découvrir le remède approprié, vous devez d'abord comprendre ce que votre code tente d'accomplir.

Exemple :comment une portée de variable erronée peut entraîner une erreur "Impossible de trouver le symbole"

List<String> stringsVar = ...

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

Pour i dans l'instruction if, cela entraînera un problème "Impossible de trouver le symbole". Même si nous avons précédemment déclaré i, cela ne s'applique qu'à l'instruction for et à son corps. La référence de l'instruction if à i ne peut pas voir cette déclaration de I car elle n'entre pas dans le cadre du projet. Une correction appropriée consisterait à placer l'instruction if dans la boucle ou à déclarer I avant le début de la boucle.)

Exemple :un problème apparemment étrange "Impossible de trouver le symbole" causé par une faute de frappe

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

Cela entraînera une erreur de compilation dans l'appel println, indiquant que i est manquant. Mais (comme vous le soulignez), nous l'avons déclaré !

Le problème est le point-virgule (;) qui apparaît avant le {. Dans ce cas, un point-virgule est une instruction vide selon la syntaxe du langage Java. Le corps de la boucle for est donc constitué de l'instruction vide. Voici donc ce que signifie réellement ce code :

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

// The previous and following are separate statements!!

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

La déclaration précédente de i dans l'instruction for est hors de portée dans le bloc. C'est parce que le bloc {…} n'est pas le corps de la boucle for.

Exemple :Une erreur "Impossible de trouver le symbole" produite par une faute de frappe

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

Le tmp dans la phrase tmp(…) est incorrect, malgré la déclaration précédente. Le compilateur cherchera une méthode tmp, mais il n'en trouvera pas. Le tmp précédemment spécifié se trouve dans l'espace de noms des variables, pas dans l'espace de noms des méthodes. Dans l'un des exemples que nous avons vus, le programmeur avait oublié d'inclure un opérateur. Voici ce qu'il voulait écrire :

int res = tmp * (a + b);

Si vous compilez à partir de la ligne de commande, il y a une autre raison pour laquelle le compilateur peut ne pas découvrir un symbole. Il est possible que vous ayez simplement négligé de construire ou de recompiler une autre classe.

Par exemple, supposons que vous ayez deux classes, secondaire et primaire, et que le secondaire utilise le primaire. Si vous n'avez jamais compilé Primary auparavant et exécuté javac Secondary.java, le compilateur échouera probablement car il ne trouvera pas le symbole Primary.

Compilez Secondaire et Primaire ensemble, par exemple, avec javac Secondaire.java Primaire.java ou javac *.java. Mieux encore, utilisez un outil de compilation Java tel que Ant, Maven, Gradle, etc.

Conclusion

L'erreur de symbole introuvable, également connue sous le nom de symbole introuvable et symbole impossible à résoudre, est une erreur de compilation Java qui se produit lorsque le compilateur ne peut pas déterminer à quoi se réfère un identifiant dans le code source. Comme pour tout autre défaut de compilation, il est essentiel de déterminer ce qui en est la cause, d'isoler le problème et de le résoudre efficacement.

Cette erreur est principalement causée par la référence à des variables et méthodes non déclarées, par exemple en les orthographiant mal ou en ne parvenant pas à importer leur package associé. Comme on le voit dans cet article, une fois qu'un problème a été identifié, le résoudre est relativement simple.


Balise Java