Che cosa significa un errore "Impossibile trovare il simbolo" o "Impossibile risolvere il simbolo"?


395

Spiegare quanto segue sugli errori "Impossibile trovare il simbolo" e "Impossibile risolvere il simbolo":

  • Cosa vogliono dire?
  • Quali cose possono causarli?
  • Come fa il programmatore a risolverli?

Questa domanda ha lo scopo di seminare una domanda e risposta esaustiva su questi errori di compilazione comuni in Java.

Risposte:


417

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 42e '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è StringBiulderinvece di StringBuilder. Java non può e non tenterà di compensare errori di ortografia o digitazione errati.
    • Forse hai sbagliato il caso; cioè stringBuilderinvece di StringBuilder. Tutti gli identificatori Java fanno distinzione tra maiuscole e minuscole.
    • Forse hai usato i trattini bassi in modo inappropriato; cioè mystringe my_stringsono 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:

    • Forse stai cercando di fare riferimento a un metodo o campo ereditato che non è stato dichiarato nelle classi o interfacce padre / antenato.
    • Forse stai provando a fare riferimento a un metodo o campo che non esiste (cioè non è stato dichiarato) nel tipo che stai utilizzando; ad es . "someString".push()2 .
    • Forse stai cercando di utilizzare un metodo come campo o viceversa; es . "someString".lengtho someArray.length().
    • Forse stai operando erroneamente su un array anziché su un elemento array; per esempio

      String strings[] = ...
      if (strings.charAt(3)) { ... }
      // maybe that should be 'strings[0].charAt(3)'
      
  • Per identificatori che dovrebbero essere nomi di classe:

    • Forse hai dimenticato di importare la classe.
    • Forse hai usato importazioni "a stella", ma la classe non è definita in nessuno dei pacchetti che hai importato.
    • Forse hai dimenticato un newcome 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 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 Filesclasse ... che java.nionon 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 ila ifdichiarazione. Sebbene in precedenza abbiamo dichiarato i, tale dichiarazione ha solo scopo per l' foraffermazione e il suo corpo. Il riferimento a inella ifdichiarazione non può vedere quella dichiarazione di i. È fuori portata .

(Una correzione appropriata qui potrebbe essere quella di spostare l' ifistruzione all'interno del ciclo o di dichiarare iprima 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 printlnchiamata dicendo che inon 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 forloop. 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 forciclo, e quindi la dichiarazione precedente inella foraffermazione è 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, tmpl' tmp(...)espressione in è errata. Il compilatore cercherà un metodo chiamato tmpe non ne troverà uno. Il precedentemente dichiarato si tmptrova 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 Fooe Bardove Foousi Bar. Se non hai mai compilato Bared esegui javac Foo.java, sei tenuto a scoprire che il compilatore non riesce a trovare il simbolo Bar. La semplice risposta è compilare Fooe Barinsieme; es . javac Foo.java Bar.javao 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 forin for (int j = 1; j < 10; j++)- probabilmente corretto.
  • Potrei aggiungere una dichiarazione j prima del forciclo interno o del forciclo esterno - possibilmente corretta.
  • Potrei passare ja inel forciclo 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.

  1. 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.

  2. 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 ...

  3. 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 -tvfper elencare il contenuto del file JAR sospetto.

  4. 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 .

  5. Problemi con Android : quando stai programmando per Android e hai errori "Impossibile trovare il simbolo" R, tieni presente che i Rsimboli sono definiti dal context.xmlfile. Verificare che il context.xmlfile sia corretto e nella posizione corretta e che il Rfile 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.

  6. 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 Stringe che la sua versione della classe non definiva un substringmetodo.

    Lezione: non definire le tue classi con gli stessi nomi delle classi di biblioteca comuni!

  7. 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 \uxxxxescape 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 .


Ho avuto un'altra situazione in cui si è verificato questo errore di compilazione mentre eclipse non ha riscontrato il problema: due classi con dipendenze definite rispettivamente nell'altra classe. Nel mio caso ho avuto un enum, implementando un'interfaccia, definita in una classe in cui ho usato follemente l'enum.
Jogi,

In qualche modo simile al commento sopra, quando compilo ed eseguo il mio programma da Eclipse non funziona nessun problema. La compilazione dalla console genera molti di questi errori "Impossibile trovare il simbolo", spesso correlati all'ultimo elemento di un'importazione. Non ho idea di cosa stia causando questo perché non c'è davvero nulla di sbagliato nel codice.
Andres Stadelmann,

Un altro problema è che gli IDE possono "interpretare" altri errori in questa categoria. Per esempio printlnin System.out.printlnse posti a livello di classe sotto compilatore standard darebbe noi <identifier> expected( demo ), ma in IntelliJ vedremo Cannot resolve symbol 'println'( demo ).
Pshemo,

Wow. Lo definirei un bug del compilatore.
Stephen C

23

Riceverai anche questo errore se dimentichi un new:

String s = String();

contro

String s = new String();

perché la chiamata senza la newparola chiave proverà a cercare un metodo (locale) chiamato Stringsenza argomenti e probabilmente la firma del metodo non è definita.


14

Un altro esempio di "Variabile è fuori portata"

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 circostanti .

Potresti dire: "Ma una variabile denominata messaggio è definita in entrambi i modi, quindi il messaggio è definito dopo il if".

Ma ti sbaglieresti.

Java non ha free()o deleteoperatori, 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 brutto 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" -> e il gioco è fatto.

Il modo più comune di gestire questo tipo di problemi relativi all'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);

4
"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)." - Se vero, questo non è rilevante. C e C ++ hanno rispettivamente operatori free / delete, eppure il codice C / C ++ equivalente ai tuoi esempi sarebbe illegale. I blocchi C e C ++ limitano l'ambito delle variabili proprio come in Java. In realtà, questo è vero per la maggior parte delle lingue "a blocchi".
Stephen C,

1
La soluzione migliore per il codice che assegna un valore diverso su ogni ramo è utilizzare una dichiarazione di variabile vuotafinal .
Daniel Pryden,

10

Un modo per ottenere questo errore in Eclipse:

  1. Definire una classe Ain src/test/java.
  2. Definire un'altra classe Bin src/main/javaquella classe usi A.

Risultato: Eclipse compilerà il codice, ma maven fornirà "Impossibile trovare il simbolo".

Causa sottostante: Eclipse sta usando un percorso di costruzione combinato per l'albero principale e di test. Sfortunatamente, non supporta l'utilizzo di percorsi di compilazione diversi per parti diverse di un progetto Eclipse, che è ciò che Maven richiede.

Soluzione:

  1. Non definire le tue dipendenze in quel modo; cioè non commettere questo errore.
  2. Costruisci regolarmente la tua base di codice usando Maven in modo da poter rilevare questo errore in anticipo. Un modo per farlo è utilizzare un server CI.

Qual è la soluzione a questo?

2
tutto ciò che usi in src / main / java deve essere definito in src / main / java o in qualsiasi dipendenza di compilazione / runtime (non dipendenze di test).
Joel Costigliola il

5

"Impossibile trovare" significa che, compilatore che non riesce a trovare la variabile, il metodo, la classe appropriati ecc ... se hai ottenuto quel massaggio di errore, prima di tutto vuoi trovare la riga di codice dove ottenere il massaggio di errore ... E poi lo farai in grado di trovare quale variabile, metodo o classe non ha definito prima di usarlo. Dopo la conferma inizializzare quella variabile, metodo o classe che possono essere utilizzati per un successivo bisogno ... Considerare il seguente esempio.

Creerò una classe demo e stamperò un nome ...

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

Ora guarda il risultato ..

inserisci qui la descrizione dell'immagine

Questo errore dice "Impossibile trovare il nome della variabile". La definizione e l'inizializzazione del valore per la variabile "name" possono essere aboliti da quell'errore ... In realtà,

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

             String name="smith";

             System.out.print(name);
      }
}

Ora guarda il nuovo output ...

inserisci qui la descrizione dell'immagine

Ok Risolto con successo quell'errore ... Allo stesso tempo, se fosse possibile ottenere "Impossibile trovare il metodo" o "Impossibile trovare la classe" qualcosa, Inizialmente, definire una classe o un metodo e dopo usarlo ..


3

Se stai riscontrando questo errore nella build da qualche altra parte, mentre il tuo IDE dice che tutto va perfettamente bene, quindi controlla che stai utilizzando le stesse versioni Java in entrambi i posti.

Ad esempio, Java 7 e Java 8 hanno API diverse, quindi la chiamata di un'API inesistente in una versione Java precedente causerebbe questo errore.


2

Anch'io stavo ricevendo questo errore. (per il quale ho cercato su Google ed ero diretto 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. Stavo ottenendo il seguente errore:

error: cannot find symbol

Soluzione: ho risolto questo problema creando innanzitutto il progetto in cui è definito il metodo, quindi il progetto da cui è stato chiamato il metodo.


Sì, questo può accadere se si decide di spostare alcune funzioni riutilizzabili dal pacchetto corrente nel pacchetto utils comune, ad esempio, ma poi si dimentica di compilare il pacchetto comune prima di chiamare la funzione dal pacchetto corrente.
buildingKofi

2

Se il percorso di build Java di eclipse è mappato su 7, 8 e in Project pom.xml Proprietà Maven java.version è menzionata una versione Java superiore (9,10,11, ecc.) Di 7,8, è necessario aggiornare in pom. file xml.

In Eclipse se Java è mappato a Java versione 11 e in pom.xml è mappato a Java versione 8. Aggiornare il supporto Eclipse a Java 11 eseguendo i passaggi seguenti nella Guida 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 sul progetto Debug come -> Maven clean, passi di creazione Maven



1

Possono esserci vari scenari come le persone hanno menzionato sopra. Un paio di cose che mi hanno aiutato a risolvere questo.

  1. Se si utilizza IntelliJ

    File -> 'Invalidate Caches/Restart'

O

  1. 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!


1

hai compilato il tuo codice usando maven compilate e poi hai usato maven test per eseguirlo ha funzionato bene. Ora se hai cambiato qualcosa nel tuo codice e poi senza compilarlo lo stai eseguendo, otterrai questo errore.

Soluzione: compilarlo nuovamente e quindi eseguire test. Per me ha funzionato in questo modo.


1

Nel mio caso - ho dovuto eseguire le seguenti operazioni:

  1. Spostare context.xmlfile src/java/packagealla resourcedirectory (IntelliJ IDE)
  2. targetDirectory pulita .

Lo spostamento del file senza preoccuparsi dei riferimenti potrebbe causare questo errore. L'ho già incontrato. Basta resettare su Git e spostare di nuovo con attenzione, l'errore si risolve.
Huy Hóm Hỉnh,

0

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] \ applicazioni \ xxxxx.java: errore [44,30]: impossibile trovare il simbolo

Un'altra causa è il metodo non supportato per la versione java che dice jdk7 vs 8. Controlla il tuo% JAVA_HOME%


Questo dice solo la stessa cosa che dicono altre risposte.
Stephen C,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.