Bitte erläutern Sie den Fehler "Symbol wurde nicht gefunden":
Diese Frage soll eine umfassende Frage zu Kompilierungsfehlern "Symbol nicht gefunden" in Java sein.
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:
true
, false
, class
, while
und so weiter.42
Und 'X'
Und "Hi mum!"
.+
, =
, {
Und so weiter.Reader
, i
, toString
, processEquibalancedElephants
und so weiter.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.
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:
StringBiulder
anstelle von StringBuilder
. Java kann und wird nicht versuchen, falsche Schreib- oder Tippfehler auszugleichen.stringBuilder
anstelle von StringBuilder
. Alle Java Bezeichner unterscheiden zwischen Groß- und Kleinschreibung.mystring
und my_string
sind unterschiedlich. (Wenn Sie sich an die Java -Stilregeln halten, sind Sie vor diesem Fehler weitgehend geschützt ...)Für Bezeichner, die Methoden- oder Feldnamen sein sollten:
"someString".Push()
2."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 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:
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 Foo
Bar
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.
Im Allgemeinen fangen Sie an, indem Sie herausfinden, wasden Kompilierungsfehler verursacht hat.
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:
for
in for (int j = 1; j < 10; j++)
ändern - wahrscheinlich richtig.j
vorder inneren for
Schleife oder der äußeren for
Schleife hinzufügen - möglicherweise richtig .j
in i
in der inneren for
Schleife ändern - wahrscheinlich falsch!Der Punkt ist, dass Siebenötigen, um zu verstehen, was Ihr Code versucht, um die richtige Lösung zu finden.
Hier sind einige Fälle, in denen das "Symbol nicht gefunden" scheinbar unerklärlich ist ... bis Sie genauer hinsehen.
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.
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 ...
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.
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 .
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!
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.
Diese Fehlermeldung wird auch angezeigt, wenn Sie eine new
vergessen:
String s = String();
versus
String s = new String();
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);
Eine Möglichkeit, diesen Fehler in Eclipse zu erhalten:
A
in src/test/Java
.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:
"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 ..
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 ...
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 ..
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.
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
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%.
Wie bereits erwähnt, kann es verschiedene Szenarien geben. Ein paar Dinge, die mir geholfen haben, dieses Problem zu lösen.
Wenn Sie IntelliJ verwenden
File -> 'Invalidate Caches/Restart'
OR
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!
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.
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.