Che cosa significa un errore di compilazione “Imansible trovare il simbolo”?

Si prega di spiegare quanto segue sull’errore “Imansible trovare il simbolo”:

  • Cosa significa questo errore?
  • Quali cose possono causare questo errore?
  • Come fa il programmatore a risolvere questo errore?

Questa domanda è progettata per essere una domanda completa sugli errori di compilazione “imansible trovare il simbolo” in Java.

1. Che cosa significa un errore “Imansible trovare il simbolo”?

Innanzitutto, è un errore di compilazione 1 . Significa che c’è un problema nel codice sorgente Java o c’è un problema nel modo in cui lo si sta compilando.

Il codice sorgente Java comprende le 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 “Imansible trovare il simbolo” riguarda gli identificatori. Quando il tuo codice è compilato, il compilatore ha bisogno di capire cosa significano tutti gli identificativi del tuo codice.

Un errore “Imansible trovare il simbolo” significa che il compilatore non può farlo. Il tuo codice sembra riferirsi a qualcosa che il compilatore non capisce.

2. Che cosa può causare un errore “Imansible trovare il simbolo”?

Come primo ordine, c’è una sola causa. Il compilatore ha esaminato tutti i punti in cui l’identificatore deve essere definito e non è stato in grado di trovare la definizione. Questo potrebbe essere causato da un numero di cose. I comuni sono i seguenti:

  • Per gli 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 di digitazione.
    • Forse hai sbagliato il caso; cioè stringBuilder invece di StringBuilder . Tutti gli identificatori Java sono case sensitive.
    • Forse hai usato underscore in modo inappropriato; cioè mystring e my_string sono diversi. (Se ti attieni alle regole dello stile Java, sarai in gran parte protetto da questo errore …)
    • Forse stai cercando di usare qualcosa che è stato dichiarato “da qualche altra parte”; cioè in un contesto diverso da quello in cui hai implicitamente detto al compilatore di guardare. (Una class diversa? Un ambito diverso? Un pacchetto diverso? Un codice diverso?)
  • Per identificatori che dovrebbero fare riferimento a variabili:
    • Forse hai dimenticato di dichiarare la variabile.
    • Forse la dichiarazione delle variabili è fuori ambito nel punto in cui hai provato ad usarlo. (Vedi esempio sotto)
  • Per identificatori che dovrebbero essere nomi di metodi o campi:
    • Forse stai provando a fare riferimento a un metodo o campo ereditato che non è stato dichiarato nelle classi o interfacce padre / antenato.
    • Forse stai provando ad usare un metodo come un campo, o viceversa; ad esempio "someString".length o someArray.length() .
  • Per identificatori che dovrebbero essere nomi di classi:

    • Forse hai dimenticato di importare la class.
    • Forse hai usato le importazioni “a stella”, ma la class 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 stavi aspettando di avere:

    • Forse hai dichiarato una class nidificata o un parametro generico che ombreggia il tipo che intendevi usare.
    • Forse stai seguendo una variabile statica o di istanza.
    • Forse hai importato il tipo sbagliato; ad es. a causa del completamento dell’IDE o dell’auto-correzione.
    • Forse stai usando (compilando contro) la versione sbagliata di un’API.
    • Forse hai dimenticato di lanciare il tuo object in una sottoclass appropriata.

Il problema è spesso una combinazione di quanto sopra. Ad esempio, forse “stella” ha importato java.io.* e poi provato a usare la class Files … che è in java.nio non java.io O forse intendevi scrivere File … che è una class in java.io


Ecco un esempio di come l’ambito della variabile errato può portare a un errore “Imansible trovare il simbolo”:

 for (int i = 0; i < strings.size(); i++) { if (strings.get(i).equalsIgnoreCase("fnoord")) { break; } } if (i < strings.size()) { ... } 

Questo darà un errore "Imansible trovare il simbolo" per i nella dichiarazione if . Anche se in precedenza abbiamo dichiarato i , quella dichiarazione è valida solo per l'istruzione for e il suo corpo. Il riferimento a i nell'istruzione if non può vedere quella dichiarazione di i . È fuori portata .

(Una correzione appropriata qui potrebbe essere quella di spostare l'istruzione if all'interno del ciclo, o di dichiarare i prima dell'inizio del ciclo.)


Ecco un esempio che provoca la perplessità in cui un errore di battitura porta a un errore "Imansible 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 chiamata println che dice che non posso essere trovato. Ma (ti sento dire) l'ho dichiarato!

Il problema è il subdolo punto e virgola prima del { . Il linguaggio Java definisce che essere un'istruzione vuota . Quindi quel codice in realtà significa questo:

 for (int i = 0; i < 100; i++); { System.out.println("i is " + i); } 

Il blocco { ... } NON è il corpo del ciclo for , quindi la dichiarazione di i non è nell'ambito del blocco.


Ecco un altro esempio di errore "Imansible trovare il simbolo" che è causato da un errore di battitura.

 int tmp = ... int res = tmp(a + b); 

Nonostante la dichiarazione precedente, il tmp nell'espressione tmp(...) è errato. Il compilatore cercherà un metodo chiamato tmp e non ne troverà uno. Il tmp precedentemente dichiarato è nel namespace 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'altra ragione 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 class. Ad esempio, se hai le classi Foo e Bar cui Foo utilizza la Bar . Se non hai mai compilato Bar ed esegui javac Foo.java , potresti scoprire che il compilatore non riesce a trovare il simbolo Bar . La semplice risposta è a Foo e Bar insieme; ad es. javac Foo.java Bar.java o javac *.java . O meglio ancora usare uno strumento di compilazione Java; ad es. Ant, Maven, Gradle e così via.

Ci sono anche altre cause più oscure ... di cui parlerò qui sotto.

3. Come posso correggere questi errori?

In generale, inizi a capire cosa ha causato l'errore di compilazione.

  • Guarda la riga nel file indicato dal messaggio di errore della compilazione.
  • Identificare il simbolo di cui parla il messaggio di errore.
  • Capire perché il compilatore sta dicendo che non riesce a trovare il simbolo; vedi sopra!

Poi pensi a cosa dovrebbe dire il tuo codice. Quindi, alla fine, stabilisci quale correzione devi apportare al codice sorgente per fare ciò 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 "Imansible trovare il simbolo" per j . Ci sono molti modi in cui posso "aggiustare" quello:

  • Potrei cambiare l'interno for for (int j = 1; j < 10; j++) - probabilmente corretto.
  • Potrei aggiungere una dichiarazione per j prima del ciclo for interno, o il ciclo for esterno - possibilmente corretta.
  • Potrei cambiare j in nel loop interno - probabilmente sbagliato!
  • e così via.

Il punto è che devi capire cosa sta cercando di fare il codice per trovare la soluzione giusta.

4. Cause oscure

Qui ci sono un paio di casi in cui il "Imansible trovare il simbolo" è apparentemente inesplicabile ... finché non si guarda più da vicino.

  1. Dipendenze errate : se si utilizza un IDE o uno strumento di compilazione che gestisce il percorso di costruzione e le dipendenze del progetto, è ansible che si sia verificato un errore con le dipendenze; es. ha lasciato fuori una dipendenza, o ha selezionato la versione sbagliata. Se stai usando uno strumento di costruzione (Ant, Maven, Gradle, ecc.), Controlla il file di costruzione del progetto. Se si utilizza un IDE, controllare la configurazione del percorso di generazione 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 hanno 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 rincorrere la coda alla ricerca di un errore illusorio che è in realtà causato non ricompilando il codice correttamente, e simili ...

  3. Un problema di build precedente : è ansible che una build precedente abbia avuto esito negativo in un modo che ha fornito un file JAR con classi mancanti. Tale errore si noterebbe in genere se si stesse utilizzando uno strumento di compilazione. Tuttavia, se stai ricevendo file JAR da qualcun altro, dipendi dal loro corretto sviluppo e noti errori. Se si sospetta ciò, utilizzare tar -tvf per elencare il contenuto del file JAR sospetto.

  4. Problemi relativi all'IDE : le persone hanno segnalato casi in cui il loro IDE viene confuso e il compilatore dell'IDE non riesce a trovare una class esistente ... o la situazione inversa.

    • Questo può accadere se le cache dell'IDE non vengono sincronizzate con il file system. Ci sono modi specifici IDE per risolverlo.

    • Questo potrebbe essere un bug dell'IDE. Ad esempio, @Joel Costigliola descrive uno scenario in cui Eclipse non gestisce correttamente un albero "test" di Maven: vedi questa risposta .

  5. Ridefinizione delle classi di sistema : ho visto casi in cui il compilatore si lamenta che la 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 class non definiva i metodi di substring .

    Lezione: non definire le tue classi con lo stesso nome delle classi di libreria comuni!

  6. Homoglyphs: se usi la codifica UTF-8 per i tuoi file sorgente, è ansible avere identificatori che sembrano uguali, ma in realtà sono diversi perché contengono omoglyph. Vedi questa pagina per maggiori informazioni.

    Puoi evitare ciò limitando te stesso ad ASCII o Latin-1 come codifica del file sorgente e usando Java \uxxxx per altri caratteri.


1 - Se, per caso, lo si vede in un'eccezione di runtime o un messaggio di errore, allora si è configurato l'IDE per eseguire il codice con errori di compilazione oppure l'applicazione sta generando e compilando il codice .. in fase di esecuzione.

Avrai anche questo errore se dimentichi una new :

 String s = String(); 

contro

 String s = new String(); 

Un altro esempio di ‘Variabile è fuori ambito’

Come ho già visto alcune volte questo tipo di domande, forse un altro esempio di ciò che è illegale anche se potrebbe sentirsi a posto .

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. Poiché nessuna delle variabili denominate message è visibile al di fuori del rispettivo scope, quali sarebbero le parentesi {} circostanti in questo caso.

Si potrebbe dire: “Ma una variabile denominata messaggio è definita in entrambi i modi – quindi il messaggio è definito dopo il if “.

Ma ti sbaglieresti.

Java non ha operatori free() o delete , quindi deve fare affidamento sul monitoraggio dell’oscilloscopio 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’è il codice duplicato, tiriamo fuori quella linea comune” -> e eccola lì.

Il modo più comune per gestire questo tipo di ambito: il problema sarebbe assegnare in precedenza i valori else ai nomi delle variabili nell’ambito esterno e quindi riassegnare in 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:

  1. Definire una class A in src/test/java .
  2. Definisci un’altra class B in src/main/java che utilizza la class A

Risultato: Eclipse compilerà il codice, ma Maven darà “Imansible trovare il simbolo”.

Causa sottostante: Eclipse utilizza un percorso di build combinato per alberi principali e di test. Sfortunatamente, non supporta l’utilizzo di percorsi di compilazione diversi per le diverse parti di un progetto Eclipse, che è ciò che richiede Maven.

Soluzione:

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

Se stai riscontrando questo errore nella build da qualche altra parte, mentre l’IDE dice che tutto è perfettamente a posto, controlla di utilizzare le stesse versioni Java in entrambe le posizioni.

Ad esempio, Java 7 e Java 8 hanno API diverse, quindi chiamare un’API inesistente in una versione precedente di Java potrebbe causare questo errore.

“Imansible trovare” significa che, il compilatore che non riesce a trovare la variabile, il metodo, la class ecc … se hai ottenuto il messaggio 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 class non hanno definito prima di usarlo. Dopo la conferma inizializzare quella variabile, il metodo o la class può essere utilizzato per richiedere successivamente … Considerare 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 ..

inserisci la descrizione dell'immagine qui

Questo errore dice “Imansible trovare il nome della variabile” .. Definendo e inizializzando il valore per la variabile “nome” può essere eliminato quell’errore.

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

Ora guarda il nuovo output …

inserisci la descrizione dell'immagine qui

Ok Risolto con successo quell’errore..Allo stesso tempo, se potessi ottenere “Imansible trovare il metodo” o “Imansible trovare la class” qualcosa, In un primo momento, definisci una class o un metodo e dopo l’uso che ..

Anche io ho ricevuto questo errore. (per il quale ho cercato su Google e sono stato indirizzato a questa pagina)

Problema: stavo chiamando un metodo statico definito nella class di un progetto A da una class definita in un altro progetto B. Stavo ottenendo il seguente errore:

 error: cannot find symbol 

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

Per suggerimenti, guarda più vicino al nome del nome della class che genera un errore e il numero di riga, ad esempio: Errore di compilazione [ERRORE] \ applications \ xxxxx.java: [44,30] errore: imansible trovare il simbolo

Un’altra causa è il metodo non supportato di per la versione java dire jdk7 vs 8. Controlla il% JAVA_HOME%

Ci possono essere vari scenari come le persone hanno menzionato sopra. Un paio di cose che mi hanno aiutato a risolvere questo.

  1. Se stai usando IntelliJ

    File -> 'Invalidate Caches/Restart'

O

  1. La class a cui si fa riferimento era in un altro progetto e tale 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!

Puoi anche ottenere questo errore se stai dichiarando con un tipo sbagliato, come:

Booleano invece di booleano

Numero intero invece di int

stringa invece di stringa