2015-06-29 12 views
6

Durante la risoluzione di una sfida online, ho osservato il seguente comportamento di java che ho trovato un po 'strano. Ho cominciato compilando un programma lungo il seguente schema:Ordine imprevisto di errori nella compilazione java

import java.io.*; 

class WeirdJava 
{ 
    public static void main (String[] args) 
    { 
     BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); 
     String input = br.readLine(); 
     HashMap<Integer, Integer> map = new HashMap<Integer,Integer>(); 
     System.out.println("Weird Java"); 
    } 
} 

Si noti che nel programma di cui sopra, ci sono due errori:

eccezioni
  • non ho trattati che potrebbero essere scagliati dal BufferedReader.
  • Non ho importato la libreria standard util che contiene HashMap.

Ora, quando provo a compilare il programma di cui sopra, il compilatore java dà l'errore che non riesce a trovare il simbolo HashMap. Si noti che la dichiarazione che coinvolge HashMap viene dopo BufferedReader. Poi, aggiungo la seguente istruzione import al programma:

import java.util.HashMap; 

Quando compilo di nuovo il programma, questa volta il compilatore mostra errore

eccezione non dichiarata IOException; deve essere catturato o dichiarato di essere gettati

Le mie domande:

  1. Perché questo errore non gettato nel precedente tentativo di compilazione?
  2. L'ordine in cui arriva l'errore di compilazione non sembra naturale. Quali sono i principi di progettazione del compilatore che entrano in gioco durante questa routine?

risposta

4

È semplicemente l'ordine in cui la fonte viene controllata dal compilatore. In particolare, il compilatore verifica le importazioni e le risolve prima di verificare la presenza di codice che richiama metodi che possono generare eccezioni controllate.

Se si esegue javac con -verbose, si noterà che i carichi compilatore classi importate, in questo caso BufferedReader e InputStreamReader, poi carica le classi API pubbliche come Object e String:

[loading ZipFileIndexFileObject[C:\Dev\Java\jdk1.7.0_75\lib\ct.sym(META-INF/sym/rt.jar/java/io/BufferedReader.class)]] 
[loading ZipFileIndexFileObject[C:\Dev\Java\jdk1.7.0_75\lib\ct.sym(META-INF/sym/rt.jar/java/io/InputStreamReader.class)] 
]  
[loading ZipFileIndexFileObject[C:\Dev\Java\jdk1.7.0_75\lib\ct.sym(META-INF/sym/rt.jar/java/lang/Object.class)]] 
[loading ZipFileIndexFileObject[C:\Dev\Java\jdk1.7.0_75\lib\ct.sym(META-INF/sym/rt.jar/java/lang/String.class)]] 
[checking test.Test] 
[loading ZipFileIndexFileObject[C:\Dev\Java\jdk1.7.0_75\lib\ct.sym(META-INF/sym/rt.jar/java/lang/AutoCloseable.class)]] 
[loading ZipFileIndexFileObject[C:\Dev\Java\jdk1.7.0_75\lib\ct.sym(META-INF/sym/rt.jar/java/lang/System.class)]] 
[loading ZipFileIndexFileObject[C:\Dev\Java\jdk1.7.0_75\lib\ct.sym(META-INF/sym/rt.jar/java/io/InputStream.class)]] 
[loading ZipFileIndexFileObject[C:\Dev\Java\jdk1.7.0_75\lib\ct.sym(META-INF/sym/rt.jar/java/io/Reader.class)]] 
Test.java:11: error: cannot find symbol 
    HashMap<Integer, Integer> map = new HashMap<Integer,Integer>(); 

Osservando allo panoramica in this link, caricando le classi utilizzate stesso è parte della prima fase di compilazione chiamato "Parse e Enter":

Ogni albero è passata ed a Invio, che immette i simboli per tutte le definizioni incontrate nei simboli. Questo deve essere fatto prima dell'analisi degli alberi che potrebbero fare riferimento a quei simboli. L'output di questa fase è un elenco delle attività, contenente alberi che devono essere analizzati e generare file di classe.

+0

perché il compilatore non parla dell'eccezione non rilevata in questo passaggio? – Bhoot

+0

@Bhoot L'unica ragione per cui ho potuto pensare è che non ha ancora raggiunto la fase di controllo delle eccezioni non rilevate. È tornato immediatamente quando ha incontrato i tipi senza importazioni. – manouti

+0

Non sono d'accordo con questo motivo, ma sembra innaturale.Apprezzerò qualsiasi letteratura che affronta questo argomento (o qualsiasi cosa ad esso correlata). – Bhoot