0. Gibt es einen Unterschied zwischen den beiden Fehlern?
Nicht wirklich. "Symbol kann nicht gefunden werden" und "Symbol kann nicht aufgelöst werden" bedeuten dasselbe. Einige Java-Compiler verwenden eine Phrase, andere die andere.
1. Was bedeutet ein Fehler "Symbol kann nicht gefunden werden"?
Erstens ist es ein Kompilierungsfehler 1 . Dies bedeutet, dass entweder ein Problem in Ihrem Java-Quellcode vorliegt oder dass bei der Kompilierung ein Problem vorliegt .
Ihr Java-Quellcode besteht aus folgenden Elementen:
- Stichwort: wie
true
, false
, class
, while
, und so weiter.
- Literale: wie
42
und 'X'
und "Hi mum!"
.
- Betreiber und andere nicht-alphanumerische Token: wie
+
, =
, {
, und so weiter.
- Identifiers: 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 tun kann. Ihr Code scheint sich auf etwas zu beziehen, das der Compiler nicht versteht.
2. Was kann den Fehler "Symbol kann nicht gefunden werden" verursachen?
Als erste Bestellung gibt es nur eine Ursache. Der Compiler sah in all den Orten , an denen die Kennung sollte festgelegt werden, und es könnte die Definition nicht finden. Dies kann durch eine Reihe von Dingen verursacht werden. Die häufigsten sind wie folgt:
- Für Bezeichner im Allgemeinen:
- Vielleicht haben Sie den Namen falsch geschrieben; dh
StringBiulder
statt StringBuilder
. Java kann und wird nicht versuchen, falsche Rechtschreib- oder Tippfehler zu kompensieren.
- Vielleicht haben Sie den Fall falsch verstanden; dh
stringBuilder
statt StringBuilder
. Bei allen Java-Bezeichnern wird zwischen Groß- und Kleinschreibung unterschieden.
- Vielleicht haben Sie Unterstriche unangemessen verwendet; dh
mystring
und my_string
sind anders. (Wenn Sie sich an die Java-Regeln halten, sind Sie weitgehend vor diesem Fehler geschützt ...)
- Vielleicht versuchen Sie etwas zu verwenden, das als "woanders" deklariert wurde; dh in einem anderen Kontext als dem, in dem Sie den Compiler implizit angewiesen haben, nachzuschauen. (Eine andere Klasse? Ein anderer Bereich? 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, außerhalb des Gültigkeitsbereichs. (Siehe Beispiel unten)
Für Bezeichner, die Methoden- oder Feldnamen sein sollten:
Für Bezeichner, die Klassennamen sein sollten:
In Fällen, in denen Typ oder Instanz nicht das Mitglied zu haben scheint, das Sie erwartet haben:
- Möglicherweise haben Sie eine verschachtelte Klasse oder einen generischen Parameter deklariert, der den Typ überschattet, den Sie verwenden wollten.
- Möglicherweise schattieren Sie eine statische oder Instanzvariable.
- Vielleicht haben Sie den falschen Typ importiert. zB aufgrund von IDE-Vervollständigung oder automatischer Korrektur.
- Möglicherweise verwenden Sie die falsche Version einer API (kompilieren dagegen).
- Vielleicht haben Sie vergessen, Ihr Objekt in eine geeignete Unterklasse umzuwandeln.
Das Problem ist oft eine Kombination der oben genannten. Zum Beispiel haben Sie vielleicht "Stern" importiert java.io.*
und dann versucht, die Files
Klasse zu verwenden ... die in java.nio
nicht ist java.io
. Oder vielleicht wolltest du schreiben File
... das ist eine Klasse in java.io
.
Hier ist ein Beispiel dafür, wie ein falscher Gültigkeitsbereich von Variablen zu einem Fehler "Symbol kann nicht gefunden werden" 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 einem Fehler "Symbol kann nicht gefunden werden" i
in der if
Anweisung. Obwohl wir vorher erklärt i
, ist diese Erklärung nur in Rahmen für die for
Erklärung und seinen Körper. Der Verweis auf i
in der if
Erklärung kann diese Erklärung von nicht seheni
. Es ist außerhalb des Geltungsbereichs .
(Eine geeignete Korrektur könnte darin bestehen, die if
Anweisung innerhalb der Schleife zu verschieben oder i
vor dem Start der Schleife zu deklarieren .)
Hier ist ein Beispiel, das Verwirrung stiftet, wenn ein Tippfehler zu einem scheinbar unerklärlichen Fehler "Symbol kann nicht gefunden werden" führt:
for (int i = 0; i < 100; i++); {
System.out.println("i is " + i);
}
Dies gibt Ihnen einen Kompilierungsfehler im println
Aufruf, der besagt, dass i
nicht gefunden werden kann. Aber (ich höre dich sagen) ich habe es erklärt!
Das Problem ist das hinterhältige Semikolon ( ;
) vor dem {
. Die Java-Sprachsyntax definiert ein Semikolon in diesem Kontext als leere 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 ist die vorherige Deklaration von i
in der for
Anweisung im Block außerhalb des Gültigkeitsbereichs .
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 Erklärung ist das tmp
im tmp(...)
Ausdruck 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. Zum Beispiel, wenn Sie Klassen haben Foo
und Bar
wo Foo
verwendet wird Bar
. Wenn Sie noch nie kompiliert haben Bar
und ausgeführt werden javac Foo.java
, können Sie feststellen, dass der Compiler das Symbol nicht finden kann Bar
. Die einfache Antwort ist zu kompilieren Foo
und Bar
zusammen; zB javac Foo.java Bar.java
oder javac *.java
. Oder verwenden Sie besser noch ein Java-Build-Tool. zB Ant, Maven, Gradle und so weiter.
Es gibt noch einige andere dunkelere Ursachen ... auf die ich weiter unten eingehen werde.
3. Wie behebe ich diese Fehler?
Im Allgemeinen beginnen Sie herauszufinden, was verursacht den Kompilierung - Fehler.
- 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.
- Finden Sie heraus, warum der Compiler sagt, dass er das Symbol nicht finden kann. siehe oben!
Dann überlegen Sie , was Ihr Code sagen soll. Dann erarbeiten Sie schließlich, 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 "Symbol kann nicht gefunden werden" für j
. Es gibt viele Möglichkeiten, wie ich das "beheben" kann:
- Ich konnte die innere ändern
for
zu for (int j = 1; j < 10; j++)
- wahrscheinlich richtig.
- Ich könnte eine Deklaration für
j
vor der inneren for
oder der äußeren for
Schleife hinzufügen - möglicherweise richtig.
- Ich könnte sich ändern ,
j
um i
in der inneren for
Schleife - wahrscheinlich falsch!
- und so weiter.
Der Punkt ist, dass Sie verstehen müssen , was Ihr Code versucht, um die richtige Lösung zu finden.
4. Dunkle Ursachen
Hier sind einige Fälle, in denen das Symbol "Symbol nicht gefunden" scheinbar unerklärlich ist ... bis Sie genauer hinschauen.
Falsche Abhängigkeiten : Wenn Sie eine IDE oder ein Build-Tool verwenden, das den Build-Pfad und die Projektabhängigkeiten verwaltet, haben Sie möglicherweise einen Fehler mit den Abhängigkeiten gemacht. zB eine Abhängigkeit ausgelassen oder die falsche Version ausgewä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 Konfiguration des Erstellungspfads des Projekts.
Sie kompilieren nicht neu : Es kommt manchmal vor, dass neue Java-Programmierer die Funktionsweise der Java-Toolkette nicht verstehen oder keinen wiederholbaren "Erstellungsprozess" implementiert haben. zB mit einer IDE, Ant, Maven, Gradle und so weiter. In einer solchen Situation kann der Programmierer seinen Schwanz verfolgen und nach einem illusorischen Fehler suchen, der tatsächlich dadurch verursacht wird, dass der Code nicht richtig neu kompiliert wird, 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, dass diese ordnungsgemäß erstellt werden und Fehler feststellen. Wenn Sie dies vermuten, verwenden Sie, um tar -tvf
den Inhalt der verdächtigen JAR-Datei aufzulisten.
IDE-Probleme : Personen haben Fälle gemeldet, in denen ihre IDE verwirrt ist und der Compiler in der IDE keine vorhandene Klasse finden kann ... oder die umgekehrte Situation.
Dies kann passieren, wenn die IDE mit der falschen JDK-Version konfiguriert wurde.
Dies kann passieren, wenn die Caches der IDE nicht mehr mit dem Dateisystem synchronisiert 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 richtig behandelt: siehe diese Antwort .
Android-Probleme : Wenn Sie für Android programmieren und Fehler im Zusammenhang mit "Symbol kann nicht gefunden werden" haben R
, beachten Sie, dass die R
Symbole in der context.xml
Datei definiert sind . Überprüfen Sie, ob Ihre context.xml
Datei korrekt und an der richtigen Stelle ist und ob die entsprechende R
Klassendatei generiert / kompiliert wurde. Beachten Sie, dass bei den Java-Symbolen zwischen Groß- und Kleinschreibung unterschieden wird, sodass bei den entsprechenden XML-IDs auch zwischen Groß- und Kleinschreibung unterschieden wird.
Andere Symbolfehler unter Android sind wahrscheinlich auf zuvor erwähnte Gründe zurückzuführen. zB fehlende oder falsche Abhängigkeiten, falsche Paketnamen, Methoden oder Felder, die in einer bestimmten API-Version nicht vorhanden sind, Rechtschreib- / Tippfehler usw.
Systemklassen neu definieren : Ich habe Fälle gesehen, in denen sich der Compiler beschwert, dass dies substring
ein unbekanntes Symbol ist
String s = ...
String s1 = s.substring(1);
Es stellte sich heraus, dass der Programmierer eine eigene Version von erstellt hatte String
und dass seine Version der Klasse keine substring
Methoden definierte .
Lektion: Definieren Sie keine eigenen Klassen mit denselben Namen wie allgemeine Bibliotheksklassen!
Homoglyphen: Wenn Sie für Ihre Quelldateien die UTF-8-Codierung verwenden, können Bezeichner verwendet werden, die gleich aussehen , sich jedoch unterscheiden, da sie Homoglyphen enthalten. Weitere Informationen finden Sie auf dieser Seite .
Sie können dies vermeiden, indem Sie sich auf ASCII oder Latin-1 als Quelldatei-Codierung beschränken und Java- \uxxxx
Escapezeichen für andere Zeichen verwenden.
1 - Wenn, vielleicht, Sie haben sehen dies in einer Runtime - Ausnahme oder eine Fehlermeldung, dann haben Sie entweder Ihre IDE Laufcode mit Kompilierungsfehlern konfigurieren oder Ihre Anwendung generiert und Kompilieren von Code .. zur Laufzeit.
2 - Die drei Grundprinzipien des Bauingenieurwesens: Wasser fließt nicht bergauf, eine Planke ist auf der Seite stärker und man kann nicht an einer Schnur drücken .