0. C'è qualche differenza tra i due errori?
Non proprio. "Impossibile trovare il simbolo" e "Impossibile risolvere il simbolo" significano la stessa cosa. Alcuni compilatori Java usano una frase e l'altra l'altra.
1. Che cosa significa un errore "Impossibile trovare il simbolo"?
Innanzitutto, si tratta di un errore di compilazione 1 . Significa che sia c'è un problema nel codice sorgente di Java, o c'è un problema nel modo in cui si sta compilando esso.
Il codice sorgente Java è costituito dai seguenti elementi:
- 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 viene compilato il codice, il compilatore deve capire cosa significano tutti gli identificatori nel codice.
Un errore "Impossibile trovare il simbolo" significa che il compilatore non può farlo. Il tuo codice sembra riferirsi a qualcosa che il compilatore non capisce.
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 doveva essere definito e non è riuscito a trovare la definizione. Ciò potrebbe essere causato da una serie di cose. Quelli comuni sono i seguenti:
- Per identificatori in generale:
- Forse hai scritto il nome in modo errato; cioè
StringBiulder
invece di StringBuilder
. Java non può e non tenterà di compensare errori di ortografia o digitazione errati.
- Forse hai sbagliato il caso; cioè
stringBuilder
invece di StringBuilder
. Tutti gli identificatori Java fanno distinzione tra maiuscole e minuscole.
- Forse hai usato i trattini bassi in modo inappropriato; cioè
mystring
e my_string
sono diversi. (Se ti attieni alle regole di stile Java, sarai ampiamente protetto da questo errore ...)
- Forse stai cercando di usare qualcosa che è stato dichiarato "altrove"; cioè in un contesto diverso da quello in cui hai implicitamente detto al compilatore di guardare. (Una classe diversa? Un ambito diverso? Un pacchetto diverso? Una base di codice diversa?)
- Per identificatori che dovrebbero fare riferimento a variabili:
- Forse hai dimenticato di dichiarare la variabile.
- Forse la dichiarazione della variabile non rientra nel campo di applicazione nel momento in cui si è tentato di utilizzarla. (Vedi esempio sotto)
Per identificatori che dovrebbero essere nomi di metodi o campi:
Per identificatori che dovrebbero essere nomi di classe:
Per i casi in cui il tipo o l'istanza non sembra avere il membro che ti aspettavi che avesse:
- Forse hai dichiarato una classe nidificata o un parametro generico che ombreggia il tipo che intendevi utilizzare.
- Forse stai ombreggiando una variabile statica o di istanza.
- Forse hai importato il tipo sbagliato; ad es. a causa del completamento dell'IDE o della correzione automatica.
- Forse stai utilizzando (compilando) la versione errata di un'API.
- Forse hai dimenticato di lanciare il tuo oggetto in una sottoclasse appropriata.
Il problema è spesso una combinazione di quanto sopra. Ad esempio, forse hai "star" importato java.io.*
e poi hai provato a usare la Files
classe ... che java.nio
non lo è java.io
. O forse volevi scrivere File
... che è una lezione java.io
.
Ecco un esempio di come l'oscillazione variabile errata 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. Sebbene in precedenza abbiamo dichiarato i
, tale dichiarazione ha solo scopo per l' for
affermazione 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 apparentemente inspiegabile "Impossibile trovare il simbolo":
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 punto e virgola subdolo ( ;
) 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
loop. 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.
Ecco un altro esempio di errore "Impossibile trovare il simbolo" causato da un errore di battitura.
int tmp = ...
int res = tmp(a + b);
Nonostante la precedente dichiarazione, tmp
l' tmp(...)
espressione in è errata. Il compilatore cercherà un metodo chiamato tmp
e non ne troverà uno. Il precedentemente dichiarato 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 lasciato fuori 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 si sta 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
usi Bar
. Se non hai mai compilato Bar
ed esegui javac Foo.java
, sei tenuto a scoprire che il compilatore non riesce a trovare il simbolo Bar
. La semplice risposta è compilare Foo
e Bar
insieme; es . javac Foo.java Bar.java
o javac *.java
. O meglio usare ancora uno strumento di compilazione Java; ad es. Ant, Maven, Gradle e così via.
Ci sono anche altre cause più oscure ... che tratterò di seguito.
3. Come posso correggere questi errori?
In generale, si inizia capendo cosa ha causato l'errore di compilazione.
- Guarda la riga nel file indicata dal messaggio di errore della compilazione.
- Identifica il simbolo di cui parla il messaggio di errore.
- Scopri perché il compilatore sta dicendo che non riesce a trovare il simbolo; vedi sopra!
Quindi pensi a cosa dovrebbe dire il tuo codice. Quindi finalmente scopri quale correzione devi apportare al tuo codice sorgente per fare quello che vuoi.
Si noti 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 in cui potrei "riparare" che:
- Potrei cambiare l'interno
for
in for (int j = 1; j < 10; j++)
- probabilmente corretto.
- Potrei aggiungere una dichiarazione
j
prima del for
ciclo interno o del for
ciclo esterno - possibilmente corretta.
- Potrei passare
j
a i
nel for
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 "Impossibile trovare il simbolo" è apparentemente inspiegabile ... fino a quando non guardi più da vicino.
Dipendenze errate : se si utilizza un IDE o uno strumento di compilazione che gestisce il percorso di compilazione e le dipendenze del progetto, è possibile che si sia commesso un errore con le dipendenze; ad esempio lasciato fuori una dipendenza o selezionato la versione sbagliata. Se stai usando uno strumento di compilazione (Ant, Maven, Gradle, ecc.), Controlla il file di build 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 usando un IDE, una formica, un Maven, un Gradle e così via. In una situazione del genere, il programmatore può finire per inseguire la coda alla ricerca di un errore illusorio che è effettivamente causato dalla non ricompilazione corretta del codice, e simili ...
Un problema di build precedente : è possibile che una build precedente abbia avuto esito negativo in un modo che ha fornito un file JAR con classi mancanti. Un tale errore verrebbe in genere notato se si stesse utilizzando uno strumento di compilazione. Tuttavia, se si stanno ottenendo i file JAR da qualcun altro, si è dipendenti da loro costruzione corretta, e notando gli errori. Se si sospetta questo, 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ò può accadere se l'IDE è stato configurato con la versione JDK errata.
Ciò potrebbe accadere se le cache dell'IDE non fossero sincronizzate con il file system. Ci sono modi specifici IDE per risolvere questo problema.
Questo potrebbe essere un bug IDE. Ad esempio, @Joel Costigliola descrive uno scenario in cui Eclipse non gestisce correttamente un albero "test" di Maven: vedi questa risposta .
Problemi con Android : quando stai programmando per Android e hai errori "Impossibile trovare il simbolo" R
, tieni presente che i R
simboli sono definiti dal context.xml
file. Verificare che il context.xml
file sia corretto e nella posizione corretta e che il R
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 precedentemente menzionati; ad es. dipendenze mancanti o errate, nomi di pacchetti errati, metodo 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 seguente
String 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 definiva un substring
metodo.
Lezione: non definire le tue classi con gli stessi nomi delle classi di biblioteca comuni!
Omoglifi: se usi la codifica UTF-8 per i tuoi file sorgente, è possibile avere identificatori che sembrano uguali, 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 di origine e usando Java \uxxxx
escape 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 di base dell'ingegneria civile: l'acqua non scorre in salita, una tavola è più forte su un lato e non puoi spingere una corda .