Cosa significa un errore "Impossibile trovare il simbolo" o "Impossibile risolvere il simbolo"?
Spiega quanto segue sugli errori "Impossibile trovare il simbolo", "Impossibile risolvere il simbolo" o "Simbolo non trovato":
- Cosa vogliono dire?
- Quali cose possono causarli?
- Come fa il programmatore a risolverli?
Questa domanda è progettata per creare una domanda e risposta completa su questi comuni errori di compilazione in Java.
Risposte
0. C'è qualche differenza tra i due errori?
Non proprio. "Impossibile trovare il simbolo", "Impossibile risolvere il simbolo" e "Simbolo non trovato" significano tutti la stessa cosa. Diversi compilatori Java utilizzano una fraseologia diversa.
1. Cosa significa l'errore "Impossibile trovare il simbolo"?
In primo luogo, è un errore di compilazione 1 . Significa che o c'è un problema nel tuo codice sorgente Java, o c'è un problema nel modo in cui lo stai compilando.
Il tuo codice sorgente Java è costituito dalle seguenti cose:
- Parole chiave: come
true
,false
,class
,while
, e così via. - Letterali: come
42
e'X'
e"Hi mum!"
. - Operatori e altri token non alfanumerici: come
+
,=
,{
e così via. - Identificatori: come
Reader
,i
,toString
,processEquibalancedElephants
, e così via. - Commenti e spazi bianchi.
Un errore "Impossibile trovare il simbolo" riguarda gli identificatori. Quando il codice viene compilato, il compilatore deve capire cosa significa ogni identificatore nel codice.
Un errore "Impossibile trovare il simbolo" significa che il compilatore non può eseguire questa operazione. Il tuo codice sembra riferirsi a qualcosa che il compilatore non comprende.
2. Cosa può causare un errore "Impossibile trovare il simbolo"?
Come primo ordine, c'è solo una causa. Il compilatore ha cercato in tutti i punti in cui l'identificatore dovrebbe essere definito e non è riuscito a trovare la definizione. Ciò potrebbe essere causato da una serie di cose. Quelli comuni sono i seguenti:
Per gli identificatori in generale:
- Forse hai scritto il nome in modo errato; cioè
StringBiulder
invece diStringBuilder
. Java non può e non tenterà di compensare errori di ortografia o di battitura. - Forse hai sbagliato il caso; cioè
stringBuilder
invece diStringBuilder
. Tutti gli identificatori Java fanno distinzione tra maiuscole e minuscole. - Forse hai usato i trattini bassi in modo inappropriato; cioè
mystring
emy_string
sono diversi. (Se ti attieni alle regole dello stile Java, sarai ampiamente protetto da questo errore ...) - Forse stai cercando di utilizzare qualcosa che è stato dichiarato "altrove"; cioè in un contesto diverso da quello in cui hai implicitamente detto al compilatore di guardare. (Una classe diversa? Uno scopo diverso? Un pacchetto diverso? Una base di codice diversa?)
- Forse hai scritto il nome in modo errato; cioè
Per identificatori che dovrebbero fare riferimento a variabili:
- Forse ti sei dimenticato di dichiarare la variabile.
- Forse la dichiarazione della variabile è fuori ambito nel punto in cui hai provato a usarla. (Vedi esempio sotto)
Per gli identificatori che dovrebbero essere metodi o nomi di campo:
Forse stai cercando di fare riferimento a un metodo o campo ereditato che non è stato dichiarato nelle classi o nelle interfacce padre / antenato.
Forse stai cercando di fare riferimento a un metodo o campo che non esiste (cioè non è stato dichiarato) nel tipo che stai usando; ad esempio
"someString".push()
2 .Forse stai cercando di utilizzare un metodo come campo o viceversa; ad esempio
"someString".length
osomeArray.length()
.Forse stai operando erroneamente su un array piuttosto che su un elemento array; per esempio
String strings[] = ... if (strings.charAt(3)) { ... } // maybe that should be 'strings[0].charAt(3)'
Per gli identificatori che dovrebbero essere nomi di classi:
Forse ti sei dimenticato di importare la classe.
Forse hai usato le importazioni "star", ma la classe non è definita in nessuno dei pacchetti che hai importato.
Forse hai dimenticato un
new
come in:String s = String(); // should be 'new String()'
Per i casi in cui il tipo o l'istanza non sembra avere il membro che ti aspettavi avesse:
- Forse hai dichiarato una classe nidificata o un parametro generico che oscura il tipo che intendevi usare.
- Forse stai oscurando una variabile statica o di istanza.
- Forse hai importato il tipo sbagliato; ad esempio, a causa del completamento dell'IDE o della correzione automatica.
- Forse stai usando (compilando contro) la versione sbagliata di un'API.
- Forse hai dimenticato di lanciare il tuo oggetto in una sottoclasse appropriata.
Il problema è spesso una combinazione di quanto sopra. Per esempio, forse si "stella" importato java.io.*
e poi ha tentato di utilizzare la Files
classe di ... che è in java.nio
non è java.io
. O forse volevi scrivere File
... che è una lezione in java.io
.
Di seguito è riportato un esempio di come l'ambito delle variabili errato può portare a un errore "Impossibile trovare il simbolo":
List<String> strings = ...
for (int i = 0; i < strings.size(); i++) {
if (strings.get(i).equalsIgnoreCase("fnord")) {
break;
}
}
if (i < strings.size()) {
...
}
Questo darà un errore "Impossibile trovare il simbolo" per i
la if
dichiarazione. Anche se in precedenza dichiarato i
, tale dichiarazione è soltanto una portata per la for
dichiarazione e il suo corpo. Il riferimento a i
nella if
dichiarazione non può vedere quella dichiarazione di i
. È fuori portata .
(Una correzione appropriata qui potrebbe essere quella di spostare l' if
istruzione all'interno del ciclo o di dichiarare i
prima dell'inizio del ciclo.)
Ecco un esempio che causa perplessità in cui un errore di battitura porta a un errore "Impossibile trovare il simbolo" apparentemente inspiegabile:
for (int i = 0; i < 100; i++); {
System.out.println("i is " + i);
}
Questo ti darà un errore di compilazione nella println
chiamata dicendo che i
non può essere trovato. Ma (ti sento dire) l'ho dichiarato!
Il problema è il subdolo punto e virgola ( ;
) prima del {
. La sintassi del linguaggio Java definisce un punto e virgola in quel contesto come un'istruzione vuota . L'istruzione vuota diventa quindi il corpo del for
ciclo. Quindi quel codice in realtà significa questo:
for (int i = 0; i < 100; i++);
// The previous and following are separate statements!!
{
System.out.println("i is " + i);
}
Il { ... }
blocco non è il corpo del for
ciclo, e quindi la dichiarazione precedente i
nella for
affermazione è fuori portata nel blocco.
Di seguito è riportato un altro esempio di errore "Impossibile trovare il simbolo" causato da un errore di battitura.
int tmp = ...
int res = tmp(a + b);
Nonostante la dichiarazione precedente, tmp
l' tmp(...)
espressione è errata. Il compilatore cercherà un metodo chiamato tmp
e non ne troverà uno. Quello dichiarato in precedenza si tmp
trova nello spazio dei nomi per le variabili, non nello spazio dei nomi per i metodi.
Nell'esempio in cui mi sono imbattuto, il programmatore aveva effettivamente escluso un operatore. Quello che intendeva scrivere era questo:
int res = tmp * (a + b);
C'è un altro motivo per cui il compilatore potrebbe non trovare un simbolo se stai compilando dalla riga di comando. Potresti semplicemente aver dimenticato di compilare o ricompilare qualche altra classe. Ad esempio, se hai classi Foo
e Bar
dove Foo
usa Bar
. Se non hai mai compilato Bar
e corri javac Foo.java
, potresti scoprire che il compilatore non riesce a trovare il simbolo Bar
. La semplice risposta è compilare Foo
e Bar
insieme; ad esempio javac Foo.java Bar.java
o javac *.java
. O meglio ancora utilizzare uno strumento di compilazione Java; ad esempio Ant, Maven, Gradle e così via.
Ci sono anche altre cause più oscure ... che tratterò di seguito.
3. Come correggo questi errori?
In generale, si inizia cercando di capire cosa ha causato l'errore di compilazione.
- Guarda la riga nel file indicata dal messaggio di errore di compilazione.
- Identifica il simbolo di cui parla il messaggio di errore.
- Scopri perché il compilatore dice che non riesce a trovare il simbolo; vedi sopra!
Quindi pensi a cosa dovrebbe dire il tuo codice. Poi finalmente capisci quale correzione devi apportare al tuo codice sorgente per fare quello che vuoi.
Nota che non tutte le "correzioni" sono corrette. Considera questo:
for (int i = 1; i < 10; i++) {
for (j = 1; j < 10; j++) {
...
}
}
Supponiamo che il compilatore dica "Impossibile trovare il simbolo" per j
. Ci sono molti modi per "aggiustarlo":
- Potrei cambiare l'interno
for
infor (int j = 1; j < 10; j++)
- probabilmente corretto. - Potrei aggiungere una dichiarazione per
j
prima delfor
ciclo interno o delfor
ciclo esterno - possibilmente corretto. - Potrei cambiare
j
ini
nelfor
ciclo interno - probabilmente sbagliato! - e così via.
Il punto è che è necessario capire che cosa il vostro codice sta cercando di fare, al fine di trovare la soluzione giusta.
4. Cause oscure
Ecco un paio di casi in cui il simbolo "Impossibile trovare" è apparentemente inspiegabile ... finché non si guarda più da vicino.
Dipendenze errate : se stai utilizzando un IDE o uno strumento di compilazione che gestisce il percorso di compilazione e le dipendenze del progetto, potresti aver commesso un errore con le dipendenze; es. tralasciato una dipendenza o selezionata la versione sbagliata. Se stai utilizzando uno strumento di compilazione (Ant, Maven, Gradle, ecc.), Controlla il file di compilazione del progetto. Se stai usando un IDE, controlla la configurazione del percorso di compilazione del progetto.
Non stai ricompilando : a volte capita che i nuovi programmatori Java non capiscano come funziona la catena di strumenti Java, o non abbiano implementato un "processo di compilazione" ripetibile; ad esempio utilizzando un IDE, Ant, Maven, Gradle e così via. In una situazione del genere, il programmatore può finire per inseguire la coda alla ricerca di un errore illusorio che in realtà è causato dalla non ricompilazione del codice correttamente, e simili ...
Un problema di build precedente : è possibile che una build precedente non sia riuscita in un modo che ha fornito un file JAR con classi mancanti. Un tale errore sarebbe in genere notato se si stesse utilizzando uno strumento di compilazione. Tuttavia, se stai ricevendo file JAR da qualcun altro, sei dipendente dal fatto che si costruiscano correttamente e notino errori. Se si sospetta ciò, utilizzare
tar -tvf
per elencare il contenuto del file JAR sospetto.Problemi IDE : le persone hanno segnalato casi in cui il loro IDE viene confuso e il compilatore nell'IDE non riesce a trovare una classe esistente ... o la situazione inversa.
Ciò potrebbe accadere se l'IDE è stato configurato con la versione JDK errata.
Ciò potrebbe accadere se le cache dell'IDE non sono più sincronizzate con il file system. Esistono modi specifici IDE per risolverlo.
Questo potrebbe essere un bug IDE. Ad esempio @Joel Costigliola descrive uno scenario in cui Eclipse non gestisce correttamente un albero di "test" di Maven: vedi questa risposta .
Problemi con Android : quando si programma per Android e si verificano errori "Impossibile trovare il simbolo" correlati
R
, tenere presente che iR
simboli sono definiti dalcontext.xml
file. Verificare che ilcontext.xml
file sia corretto e nella posizione corretta e che ilR
file di classe corrispondente sia stato generato / compilato. Nota che i simboli Java fanno distinzione tra maiuscole e minuscole, quindi anche gli ID XML corrispondenti fanno distinzione tra maiuscole e minuscole.È probabile che altri errori di simboli su Android siano dovuti a motivi menzionati in precedenza; es. dipendenze mancanti o errate, nomi di pacchetti errati, metodi o campi che non esistono in una particolare versione dell'API, errori di ortografia / digitazione e così via.
Ridefinire le classi di sistema : ho visto casi in cui il compilatore si lamenta che
substring
è un simbolo sconosciuto in qualcosa di simile al seguenteString s = ... String s1 = s.substring(1);
Si è scoperto che il programmatore aveva creato la propria versione di
String
e che la sua versione della classe non definivasubstring
metodi.Lezione: non definire le tue classi con gli stessi nomi delle classi di libreria comuni!
Omoglyphs: se usi la codifica UTF-8 per i tuoi file sorgente, è possibile avere identificatori che hanno lo stesso aspetto , ma in realtà sono diversi perché contengono omoglifi. Vedi questa pagina per maggiori informazioni.
Puoi evitarlo limitandoti a ASCII o Latin-1 come codifica del file sorgente e utilizzando gli
\uxxxx
escape Java per altri caratteri.
1 - Se, per caso, si fanno vedere questo in un'eccezione di runtime o un messaggio di errore, allora o è stato configurato il vostro IDE per eseguire il codice con errori di compilazione, o l'applicazione è la generazione e la compilazione di codice .. in fase di esecuzione.
2 - I tre principi base dell'ingegneria civile: l'acqua non scorre in salita, una tavola è più forte su un lato e non puoi spingere su una corda .
Riceverai questo errore anche se dimentichi new
:
String s = String();
contro
String s = new String();
perché la chiamata senza la new
parola chiave proverà a cercare un metodo (locale) chiamato String
senza argomenti e probabilmente la firma del metodo non è definita.
Un altro esempio di "Variabile fuori ambito"
Come ho visto che tipo di domande un paio di volte già, forse più un esempio di ciò che è illegale anche se potrebbe sentirsi bene.
Considera questo codice:
if(somethingIsTrue()) {
String message = "Everything is fine";
} else {
String message = "We have an error";
}
System.out.println(message);
Questo è un codice non valido. Perché nessuna delle variabili nominate message
è visibile al di fuori del rispettivo ambito, che {}
in questo caso sarebbero le parentesi quadre .
Potresti dire: "Ma una variabile denominata messaggio è definita in entrambi i casi, quindi il messaggio è definito dopo if
".
Ma ti sbaglieresti.
Java non ha operatori free()
o delete
, quindi deve fare affidamento sul monitoraggio dell'ambito delle variabili per scoprire quando le variabili non vengono più utilizzate (insieme ai riferimenti a queste variabili di causa).
È particolarmente grave se pensavi di aver fatto qualcosa di buono. Ho visto questo tipo di errore dopo aver "ottimizzato" il codice in questo modo:
if(somethingIsTrue()) {
String message = "Everything is fine";
System.out.println(message);
} else {
String message = "We have an error";
System.out.println(message);
}
"Oh, c'è un codice duplicato, tiriamo fuori quella linea comune" -> ed eccolo.
Il modo più comune per affrontare questo tipo di problemi di ambito sarebbe quello di pre-assegnare i valori else ai nomi delle variabili nell'ambito esterno e quindi riassegnare se:
String message = "We have an error";
if(somethingIsTrue()) {
message = "Everything is fine";
}
System.out.println(message);
Un modo per ottenere questo errore in Eclipse:
- Definisci una classe
A
insrc/test/java
. - Definire un'altra classe
B
insrc/main/java
quella classe usiA
.
Risultato: Eclipse compilerà il codice, ma Maven darà "Impossibile trovare il simbolo".
Causa sottostante: Eclipse utilizza un percorso di compilazione combinato per gli alberi principale e di prova. Sfortunatamente, non supporta l'utilizzo di percorsi di compilazione diversi per parti diverse di un progetto Eclipse, che è ciò che richiede Maven.
Soluzione:
- Non definire le tue dipendenze in questo modo; cioè non commettere questo errore.
- Costruisci regolarmente la tua base di codice usando Maven in modo da rilevare questo errore in anticipo. Un modo per farlo è utilizzare un server CI.
"Impossibile trovare" significa che, compilatore che non riesce a trovare la variabile, il metodo, la classe, ecc. Appropriati, se hai ricevuto quel messaggio di errore, prima di tutto vuoi trovare la riga di codice dove ottenere il messaggio di errore .. E poi lo farai in grado di trovare quale variabile, metodo o classe non è stata definita prima di utilizzarla.Dopo la conferma inizializzare quella variabile, metodo o classe può essere utilizzata per richiedere in seguito ... Considera il seguente esempio.
Creerò una lezione dimostrativa e stamperò un nome ...
class demo{
public static void main(String a[]){
System.out.print(name);
}
}
Ora guarda il risultato ..
Quell'errore dice "il nome della variabile non può trovare" .. La definizione e l'inizializzazione del valore per la variabile "nome" può essere abolita. In realtà, in questo modo,
class demo{
public static void main(String a[]){
String name="smith";
System.out.print(name);
}
}
Ora guarda il nuovo output ...
Ok Ho risolto con successo l'errore ... Allo stesso tempo, se potessi ottenere qualcosa "Impossibile trovare il metodo" o "Impossibile trovare la classe", in un primo momento, definisci una classe o un metodo e dopo usalo ..
Se ricevi questo errore nella build da qualche altra parte, mentre il tuo IDE dice che è tutto perfettamente a posto, controlla di utilizzare le stesse versioni di Java in entrambi i posti.
Ad esempio, Java 7 e Java 8 hanno API diverse, quindi chiamare un'API inesistente in una versione precedente di Java causerebbe questo errore.
RISOLTO
Utilizzando IntelliJ
Seleziona Build -> Rebuild Project lo risolverà
Anch'io stavo ricevendo questo errore. (per cui ho cercato su Google e sono stato indirizzato a questa pagina)
Problema: stavo chiamando un metodo statico definito nella classe di un progetto A da una classe definita in un altro progetto B. Ricevo il seguente errore:
error: cannot find symbol
Soluzione: ho risolto questo problema creando prima il progetto in cui è definito il metodo, quindi il progetto da cui veniva chiamato il metodo.
Se il percorso di compilazione Java di eclipse è mappato a 7, 8 e nelle proprietà del progetto pom.xml Maven java.version è menzionata una versione Java superiore (9,10,11, ecc.,) Rispetto a 7,8 è necessario aggiornare in pom. xml file.
In Eclipse se Java è mappato a Java versione 11 e in pom.xml è mappato a Java versione 8. Aggiorna il supporto di Eclipse a Java 11 eseguendo i passaggi seguenti nella guida dell'IDE di eclipse -> Installa nuovo software ->
Incolla il seguente link http://download.eclipse.org/eclipse/updates/4.9-P-builds at Work With
o
Aggiungi (si aprirà la finestra popup) ->
Name:
Supporto Java 11
Location:
http://download.eclipse.org/eclipse/updates/4.9-P-builds
quindi aggiorna la versione Java nelle proprietà Maven del file pom.xml come di seguito
<java.version>11</java.version>
<maven.compiler.source>${java.version}</maven.compiler.source>
<maven.compiler.target>${java.version}</maven.compiler.target>
Infine fai clic con il pulsante destro del mouse su Debug del progetto come -> Maven clean, Maven build steps
Ci possono essere vari scenari come le persone hanno menzionato sopra. Un paio di cose che mi hanno aiutato a risolvere questo problema.
Se stai usando IntelliJ
File -> 'Invalidate Caches/Restart'
O
La classe a cui si fa riferimento era in un altro progetto e quella dipendenza non è stata aggiunta al file di build Gradle del mio progetto. Quindi ho aggiunto la dipendenza usando
compile project(':anotherProject')
e ha funzionato. HTH!
hai compilato il tuo codice usando Maven Compile e poi usato Maven test per eseguirlo ha funzionato bene. Ora se hai cambiato qualcosa nel tuo codice e quindi senza compilarlo lo stai eseguendo, otterrai questo errore.
Soluzione: compilarlo di nuovo e quindi eseguire test. Per me ha funzionato in questo modo.
Nel mio caso, ho dovuto eseguire le seguenti operazioni:
- Sposta
context.xml
file dasrc/java/package
allaresource
directory (IntelliJ IDE) target
Directory pulita .
Per suggerimenti, guarda più da vicino il nome della classe che genera un errore e il numero di riga, ad esempio: Errore di compilazione [ERRORE] \ applications \ xxxxx.java: [44,30] errore: impossibile trovare il simbolo
Un'altra causa è il metodo non supportato per la versione java, ad esempio jdk7 vs 8. Controlla il tuo% JAVA_HOME%
Abbiamo ricevuto l'errore in un progetto Java impostato come build multi-progetto Gradle. Si è scoperto che in uno dei sottoprogetti mancava il plugin Gradle Java Library . Ciò ha impedito ai file di classe del sottoprogetto di essere visibili ad altri progetti nella build.
Dopo aver aggiunto il plug-in della libreria Java al sottoprogetto build.gradle
nel modo seguente, l'errore è scomparso:
plugins {
...
id 'java-library'
}
Ho risolto questo errore in questo modo ... La follia di Android. Avevo il nome del pacchetto come adattatore e ho rifattorizzato il nome dell'adattatore con una "a" invece di "A" e ho risolto l'errore.