it-swarm.com.de

Was bedeutet ein Kompilierungsfehler "Symbol nicht gefunden"?

Bitte erläutern Sie den Fehler "Symbol wurde nicht gefunden":

  • Was bedeutet dieser Fehler?
  • Welche Dinge können diesen Fehler verursachen?
  • Wie kann der Programmierer diesen Fehler beheben?

Diese Frage soll eine umfassende Frage zu Kompilierungsfehlern "Symbol nicht gefunden" in Java sein.

318
Stephen C

1. Was bedeutet der Fehler "Symbol nicht gefunden"?

Erstens ist es einÜbersetzungsfehler1. Dies bedeutet, dassentwederein Problem in Ihrem Java Quellcode vorliegt,oderist ein Problem in der Art, wie Sie es kompilieren.

Ihr Java Quellcode besteht aus den folgenden Dingen:

  • Stichwörter: wie true, false, class, while und so weiter.
  • Literale: wie 42 Und 'X' Und "Hi mum!".
  • Operatoren und andere nicht alphanumerische Token: wie +, =, { Und so weiter.
  • Bezeichner: wie Reader, i, toString, processEquibalancedElephants und so weiter.
  • Kommentare und Leerzeichen.

Ein Fehler "Symbol kann nicht gefunden werden" betrifft die Bezeichner. Wenn Ihr Code kompiliert wird, muss der Compiler herausfinden, was jeder einzelne Bezeichner in Ihrem Code bedeutet.

Ein Fehler "Symbol kann nicht gefunden werden" bedeutet, dass der Compiler dies nicht kann. Ihr Code scheint auf etwas zu verweisen, das der Compiler nicht versteht.

2. Was kann den Fehler "Symbol nicht gefunden" verursachen?

Bei der ersten Bestellung gibt es nur eine Ursache. Der Compiler suchte an allen Stellen, an denen der Bezeichnerdefiniert werden sollte, und konnte die Definition nicht finden. Dies könnte durch eine Reihe von Dingen verursacht werden. Die häufigsten sind wie folgt:

  • Für Kennungen allgemein:
    • Vielleicht haben Sie den Namen falsch geschrieben. d. h. StringBiulder anstelle von StringBuilder. Java kann und wird nicht versuchen, falsche Schreib- oder Tippfehler auszugleichen.
    • Vielleicht hast du den Fall falsch verstanden; d. h. stringBuilder anstelle von StringBuilder. Alle Java Bezeichner unterscheiden zwischen Groß- und Kleinschreibung.
    • Vielleicht haben Sie Unterstriche unangemessen verwendet. d.h. mystring und my_string sind unterschiedlich. (Wenn Sie sich an die Java -Stilregeln halten, sind Sie vor diesem Fehler weitgehend geschützt ...)
    • Vielleicht versuchen Sie, etwas zu verwenden, das als "woanders" deklariert wurde. in einem anderen Kontext als dem, in dem Sie dem Compiler implizit befohlen haben, nachzuschauen. (Eine andere Klasse? Ein anderer Geltungsbereich? Ein anderes Paket? Eine andere Codebasis?)
  • Für Bezeichner, die sich auf Variablen beziehen sollten:
    • Vielleicht haben Sie vergessen, die Variable zu deklarieren.
    • Möglicherweise ist die Variablendeklaration an dem Punkt, an dem Sie versucht haben, sie zu verwenden, ungültig. (Siehe Beispiel unten)
  • Für Bezeichner, die Methoden- oder Feldnamen sein sollten:

    • Möglicherweise versuchen Sie, auf eine geerbte Methode oder ein geerbtes Feld zu verweisen, die bzw. das nicht in den übergeordneten/übergeordneten Klassen oder Schnittstellen deklariert wurde.
    • Möglicherweise versuchen Sie, auf eine Methode oder ein Feld zu verweisen, die bzw. das in dem von Ihnen verwendeten Typ nicht vorhanden ist (d. H. Nicht deklariert wurde). z.B. "someString".Push()2.
    • Vielleicht versuchen Sie, eine Methode als Feld zu verwenden oder umgekehrt. z.B. "someString".length Oder someArray.length().
    • Möglicherweise arbeiten Sie fälschlicherweise mit einem Array und nicht mit einem Array-Element. z.B.

      String strings[] = ...
      if (strings.charAt(3)) { ... }
      // maybe that should be 'strings[0].charAt(3)'
      
  • Für Bezeichner, die Klassennamen sein sollten:

    • Vielleicht haben Sie vergessen, die Klasse zu importieren.
    • Möglicherweise haben Sie "Stern" -Importe verwendet, aber die Klasse ist in keinem der von Ihnen importierten Pakete definiert.
    • Vielleicht haben Sie ein new vergessen, wie in:

      String s = String();  // should be 'new String()'
      
  • Für Fälle, in denen Typ oder Instanz das erwartete Mitglied nicht zu haben scheinen:

    • Vielleicht haben Sie eine verschachtelte Klasse oder einen generischen Parameter deklariert, dershadowsdem Typ, den Sie verwenden wollten.
    • Möglicherweise spiegeln Sie eine statische oder Instanzvariable.
    • Vielleicht haben Sie den falschen Typ importiert. z.B. aufgrund von IDE Abschluss oder Autokorrektur.
    • Möglicherweise verwenden Sie (kompilieren) die falsche Version einer API.
    • Möglicherweise haben Sie vergessen, Ihr Objekt in eine geeignete Unterklasse umzuwandeln.

Das Problem ist oft eine Kombination der oben genannten. Vielleicht haben Sie zum Beispiel Java.io.* Mit einem "Stern" importiert und dann versucht, die Klasse Files zu verwenden, die sich in Java.nio Und nicht in Java.io Befindet. Oder vielleicht wollten Sie File ... schreiben, wobeieine Klasse in Java.io Ist.


Hier ist ein Beispiel, wie ein inkorrekter Variablenumfang zu einem Fehler "Symbol nicht gefunden" führen kann:

List<String> strings = ...

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

Dies führt zu dem Fehler "Symbol kann nicht gefunden werden" für i in der Anweisung if. Obwohl wir zuvor i deklariert haben, ist diese Deklaration nurim Gültigkeitsbereichfür die for -Anweisung und ihren Hauptteil. Der Verweis auf i in der if-Anweisungkanndiese Deklaration von i nicht sehen. Es istout of scope.

(Eine geeignete Korrektur könnte darin bestehen, die Anweisung if innerhalb der Schleife zu verschieben oder i vor dem Beginn der Schleife zu deklarieren.)


Hier ist ein Beispiel, das Verwirrung stiftet, wenn ein Tippfehler zu einem scheinbar unerklärlichen Fehler "Symbol nicht gefunden" führt:

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

Dies führt zu einem Kompilierungsfehler beim Aufruf von println, der besagt, dass i nicht gefunden werden kann. Aber (ich höre dich sagen) ich habe es erklärt!

Das Problem ist das hinterlistige Semikolon (;) Vor dem {. Die Java Sprachensyntax definiert ein Semikolon in diesem Kontext alsleere Anweisung. Die leere Anweisung wird dann zum Hauptteil der for -Schleife. Dieser Code bedeutet also tatsächlich Folgendes:

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

// The previous and following are separate statements!!

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

Der Block { ... } Ist NICHT der Hauptteil der for -Schleife, und daher lautet die vorherige Deklaration von i in der for -Anweisungout of scopeim Block.


Hier ist ein weiteres Beispiel für den Fehler "Symbol kann nicht gefunden werden", der durch einen Tippfehler verursacht wird.

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

Trotz der vorherigen Deklaration ist der Ausdruck tmp in tmp(...) fehlerhaft. Der Compiler sucht nach einer Methode namens tmp und findet keine. Das zuvor deklarierte tmp befindet sich im Namespace für Variablen, nicht im Namespace für Methoden.

In dem Beispiel, auf das ich gestoßen bin, hatte der Programmierer tatsächlich einen Operator ausgelassen. Was er schreiben wollte, war folgendes:

int res = tmp * (a + b);

Es gibt einen weiteren Grund, warum der Compiler möglicherweise kein Symbol findet, wenn Sie über die Befehlszeile kompilieren. Möglicherweise haben Sie einfach vergessen, eine andere Klasse zu kompilieren oder neu zu kompilieren. Wenn Sie beispielsweise Klassen Foo und Bar haben, wobei FooBar verwendet. Wenn Sie Bar noch nie kompiliert haben und javac Foo.Java Ausführen, können Sie feststellen, dass der Compiler das Symbol Bar nicht finden kann. Die einfache Antwort ist, Foo und Bar zusammen zu kompilieren; z.B. javac Foo.Java Bar.Java Oder javac *.Java. Oder besser noch ein Java Build-Tool verwenden; z.B. Ameise, Maven, Gradle und so weiter.

Es gibt noch einige andere undurchsichtige Ursachen, auf die ich weiter unten eingehen werde.

3. Wie behebe ich diese Fehler?

Im Allgemeinen fangen Sie an, indem Sie herausfinden, wasden Kompilierungsfehler verursacht hat.

  • Sehen Sie sich die Zeile in der Datei an, die in der Kompilierungsfehlermeldung angegeben ist.
  • Identifizieren Sie, um welches Symbol es sich bei der Fehlermeldung handelt.
  • Finde heraus,warumder Compiler sagt, dass er das Symbol nicht finden kann; siehe oben!

Dannüberlege dir, was dein Code sagen soll. Schließlich erarbeiten Sie, welche Korrektur Sie an Ihrem Quellcode vornehmen müssen, um das zu tun, was Sie wollen.

Beachten Sie, dass nicht jede "Korrektur" korrekt ist. Bedenken Sie:

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

Angenommen, der Compiler sagt "Kann Symbol nicht finden" für j. Es gibt viele Möglichkeiten, wie ich das "beheben" kann:

  • Ich könnte das innere for in for (int j = 1; j < 10; j++) ändern - wahrscheinlich richtig.
  • Ich könnte eine Deklaration für jvorder inneren for Schleife oder der äußeren for Schleife hinzufügen - möglicherweise richtig .
  • Ich könnte j in i in der inneren for Schleife ändern - wahrscheinlich falsch!
  • und so weiter.

Der Punkt ist, dass Siebenötigen, um zu verstehen, was Ihr Code versucht, um die richtige Lösung zu finden.

4. Dunkle Ursachen

Hier sind einige Fälle, in denen das "Symbol nicht gefunden" scheinbar unerklärlich ist ... bis Sie genauer hinsehen.

  1. Inkorrekte Abhängigkeiten: Wenn Sie ein IDE oder ein Erstellungswerkzeug verwenden, das den Erstellungspfad und die Projektabhängigkeiten verwaltet, haben Sie möglicherweise einen Fehler mit den Abhängigkeiten gemacht. z.B. eine Abhängigkeit ausgelassen oder die falsche Version gewählt. Wenn Sie ein Build-Tool (Ant, Maven, Gradle usw.) verwenden, überprüfen Sie die Build-Datei des Projekts. Wenn Sie eine IDE verwenden, überprüfen Sie die Build-Pfad-Konfiguration des Projekts.

  2. Sie kompilieren nicht ne: Es kommt manchmal vor, dass neue Java Programmierer nicht verstehen, wie die Java Toolkette funktioniert, oder keine wiederholbaren Funktionen implementiert haben. " Erstellungsprozess "; z.B. mit einer IDE, Ant, Maven, Gradle und so weiter. In einer solchen Situation kann der Programmierer seinen Schwanz auf der Suche nach einem illusorischen Fehler verfolgen, dertatsächlichist, weil der Code nicht richtig kompiliert wurde, und dergleichen ...

  3. Ein früheres Build-Problem: Möglicherweise ist ein früherer Build auf eine Weise fehlgeschlagen, die eine JAR-Datei mit fehlenden Klassen ergab. Ein solcher Fehler wird normalerweise bemerkt, wenn Sie ein Build-Tool verwenden. Wenn Sie jedoch JAR-Dateien von einer anderen Person erhalten, sind Sie darauf angewiesen, dassdieseordnungsgemäß erstellt und Fehler festgestellt werden. Wenn Sie dies vermuten, verwenden Sie tar -tvf, Um den Inhalt der verdächtigen JAR-Datei aufzulisten.

  4. IDE issues: Leute haben Fälle gemeldet, in denen ihr IDE verwirrt ist und der Compiler in IDE keine Klasse findet, die existiert ... oder die umgekehrte Situation .

    • Dies kann passieren, wenn IDE mit der falschen JDK-Version konfiguriert wurde.

    • Dies kann passieren, wenn die Caches der IDE nicht mehr mit dem Dateisystem synchron sind. Es gibt IDE spezifische Möglichkeiten, dies zu beheben.

    • Dies könnte ein IDE Fehler sein. Zum Beispiel beschreibt @Joel Costigliola ein Szenario, in dem Eclipse einen Maven-Testbaum nicht korrekt behandelt: siehe diese Antwort ​​ .

  5. Systemklassen neu definieren: Ich habe Fälle gesehen, in denen der Compiler beklagt, dass substring in etwa der folgenden Art ein unbekanntes Symbol ist

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

    Es stellte sich heraus, dass der Programmierer eine eigene Version von String erstellt hatte und dass seine Version der Klasse keine substring -Methoden definierte.

    Lektion: Definieren Sie keine eigenen Klassen mit denselben Namen wie die gängigen Bibliotheksklassen!

  6. Homoglyphen: Wenn Sie UTF-8-Codierung für Ihre Quelldateien verwenden, ist es möglich, dass die Bezeichneraussehenidentisch sind, dies jedoch tatsächlich der Fall ist anders, weil sie Homoglyphen enthalten. Weitere Informationen finden Sie auf dieser Seite .

    Sie können dies vermeiden, indem Sie sich auf ASCII oder Latin-1 als Quellendateicodierung beschränken und Java \uxxxx Für andere Zeichen verwenden.


1 - Wenn Siedodies möglicherweise in einer Laufzeitausnahme oder Fehlermeldung sehen, haben Sie entweder IDE so konfiguriert, dass Code mit Kompilierung ausgeführt wird Fehler, oder Ihre Anwendung generiert und kompiliert Code .. zur Laufzeit.

2 - Die drei Grundprinzipien des Bauingenieurwesens: Wasser fließt nicht bergauf, ein Brett ist auf der Seite stärker undman kann nicht auf eine Schnur drücken.

368
Stephen C

Diese Fehlermeldung wird auch angezeigt, wenn Sie eine new vergessen:

String s = String();

versus

String s = new String();
21
thinkterry

Ein weiteres Beispiel für 'Variable liegt außerhalb des Gültigkeitsbereichs'

Wie ich bereits ein paar Mal gesehen habe, ist dies vielleicht ein weiteres Beispiel für das, was illegal ist, auch wenn es sich vielleicht fühle okay anfühlt.

Betrachten Sie diesen Code:

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

Das ist ungültiger Code. Da keine der Variablen mit dem Namen message außerhalb ihres jeweiligen Bereichs sichtbar ist - in diesem Fall die umgebenden Klammern {}.

Sie könnten sagen: "Aber eine Variable namens message ist so oder so definiert - also message ist definiert nach dem if".

Aber du liegst falsch.

Java hat keine free() - oder delete -Operatoren, daher muss es auf die Verfolgung des Variablenbereichs angewiesen sein, um herauszufinden, wann Variablen nicht mehr verwendet werden (zusammen mit Verweisen auf diese ursächlichen Variablen).

Es ist besonders schlimm, wenn Sie dachten, Sie hätten etwas Gutes getan. Ich habe diese Art von Fehler gesehen, nachdem ich den Code wie folgt "optimiert" habe:

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

"Oh, es gibt doppelten Code, lass uns diese gemeinsame Linie herausziehen" -> und da ist es.

Die gebräuchlichste Methode, um mit dieser Art von Problemen mit dem Gültigkeitsbereich umzugehen, besteht darin, die else-Werte den Variablennamen im externen Gültigkeitsbereich vorab zuzuweisen und sie dann erneut zuzuweisen, wenn:

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

Eine Möglichkeit, diesen Fehler in Eclipse zu erhalten: 

  1. Definieren Sie eine Klasse A in src/test/Java.
  2. Definieren Sie in src/main/Java eine weitere Klasse B, die die Klasse A verwendet.

Ergebnis: Eclipse kompiliert den Code, aber Maven gibt "Symbol nicht finden" aus.

Grundursache: Eclipse verwendet einen kombinierten Build-Pfad für die Haupt- und Testbäume. Leider unterstützt es nicht die Verwendung verschiedener Erstellungspfade für verschiedene Teile eines Eclipse-Projekts, was Maven erfordert.

Lösung: 

  1. Definieren Sie Ihre Abhängigkeiten nicht so. Machen Sie diesen Fehler nicht.
  2. Bauen Sie Ihre Codebase regelmäßig mit Maven auf, damit Sie diesen Fehler frühzeitig erkennen. Eine Möglichkeit, dies zu tun, ist die Verwendung eines CI-Servers.
8

"Kann nicht finden" bedeutet, dass der Compiler die passende Variable, Methode, Klasse usw. nicht finden kann ... Wenn Sie diese Fehlermassage erhalten haben, möchten Sie zunächst die Codezeile finden, in der die Fehlermassage ausgeführt wird In der Lage, herauszufinden, welche Variable, Methode oder Klasse nicht definiert wurde, bevor sie verwendet wird. Nach dem Bestätigen der Initialisierung kann die Variable, Methode oder Klasse für eine spätere Verwendung verwendet werden. Betrachten Sie das folgende Beispiel.

Ich werde eine Demo-Klasse erstellen und einen Namen drucken ...

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

Nun schau dir das Ergebnis an ..

 enter image description here

Dieser Fehler besagt, dass "Variablenname nicht gefunden werden kann". Durch die Definition und Initialisierung des Werts für die 'Name'-Variable kann dieser Fehler beseitigt werden. Eigentlich so,

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

             String name="smith";

             System.out.print(name);
      }
}

Nun schau dir die neue Ausgabe an ...

 enter image description here

Ok Dieser Fehler wurde erfolgreich behoben .. Gleichzeitig können Sie, wenn Sie "etwas nicht finden können" oder "Klassen nicht finden" erhalten, etwas definieren. Definieren Sie zunächst eine Klasse oder Methode und stellen Sie anschließend fest, dass .. 

3
GT_hash

Wenn Sie diesen Fehler an einem anderen Ort erhalten, während Ihre IDE sagt, dass alles in Ordnung ist, überprüfen Sie, ob Sie an beiden Stellen die gleichen Java-Versionen verwenden.

Java 7 und Java 8 verfügen beispielsweise über unterschiedliche APIs. Der Aufruf einer nicht vorhandenen API in einer älteren Java-Version würde diesen Fehler verursachen.

2
Jonathan Lin

Wenn der Eclipse-Erstellungspfad Java auf 7, 8 und in Project pom.xml Maven-Eigenschaften zugeordnet ist, wird Java.version in einer höheren Version Java (9, 10, 11 usw.) als 7 erwähnt. 8 Sie müssen in der Datei pom.xml aktualisieren.

Wenn in Eclipse Java Java Version 11 und in pom.xml Java Version 8 zugeordnet ist, führen Sie die folgenden Schritte aus, um die Eclipse-Unterstützung auf Java 11 zu aktualisieren in der Eclipse-Hilfe IDE -> Neue Software installieren ->

Fügen Sie folgenden Link ein http://download.Eclipse.org/Eclipse/updates/4.9-P-builds at Work With

oder

Hinzufügen (Popup-Fenster öffnet sich) ->

Name: Java 11-Unterstützung Location:http://download.Eclipse.org/Eclipse/updates/4.9-P-builds

aktualisieren Sie anschließend die Java - Version in den Maven-Eigenschaften der Datei pom.xml wie unten beschrieben

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

Zum Schluss machen Sie einen Rechtsklick auf das Projekt Debuggen als -> Maven bereinigen, Maven bauen

1
pudaykiran

Weitere Hinweise finden Sie unter dem Klassennamen, der einen Fehler ausgibt, und der Zeilennummer. Beispiel: Kompilierungsfehler [ERROR]\applications\xxxxx.Java: [44,30] Fehler: Symbol kann nicht gefunden werden

Eine andere Ursache ist die nicht unterstützte Methode für Java-Version, beispielsweise jdk7 vs 8 . Überprüfen Sie Ihre% Java_HOME%. 

0
Striker

Wie bereits erwähnt, kann es verschiedene Szenarien geben. Ein paar Dinge, die mir geholfen haben, dieses Problem zu lösen.

  1. Wenn Sie IntelliJ verwenden

    File -> 'Invalidate Caches/Restart'

OR

  1. Die Klasse, auf die verwiesen wird, befand sich in einem anderen Projekt und diese Abhängigkeit wurde der Gradle-Builddatei meines Projekts nicht hinzugefügt. Also habe ich die Abhängigkeit mit hinzugefügt

    compile project(':anotherProject')

und es hat funktioniert. HTH!

0
avp

sie haben Ihren Code mit maven compile kompiliert und anschließend mit maven test ausgeführt. Wenn Sie jetzt etwas in Ihrem Code geändert haben und ihn dann ohne Kompilierung ausführen, wird dieser Fehler angezeigt.

Lösung: Kompilieren Sie es erneut und führen Sie dann den Test aus. Bei mir hat es so geklappt.

0
ANIL KUMAR

Auch ich habe diesen Fehler bekommen. (für die ich gegoogelt habe und auf diese Seite verwiesen wurde)

Problem: Ich habe eine in der Klasse eines Projekts A definierte statische Methode aus einer in einem anderen Projekt definierten Klasse B aufgerufen. Ich hatte die folgende Fehlermeldung:

error: cannot find symbol

Lösung: Ich habe dies gelöst, indem ich zuerst das Projekt erstellte, in dem die Methode definiert ist, und dann das Projekt, von dem aus die Methode aufgerufen wurde.

0
Maria