2013-02-23 26 views
7

In base a JLS: è un errore in fase di compilazione se un inizializzatore di variabili di istanza o un inizializzatore di istanza di una classe denominata può generare una classe di eccezioni verificata, a meno che tale classe di eccezioni o una delle sue superclassi non sia dichiarata esplicitamente nella clausola throws di ogni costruttore della sua classe e la classe ha almeno un costruttore dichiarato esplicitamente.Blocco di inizializzazione e inizializzazione selezionato

Quindi, se faccio questo -

class A{ 
{ 
    throw new FileNotFoundException(); 
} 
public A() throws IOException{ 
    // TODO Auto-generated constructor stub 
} 
} 

Questo dà un errore di compilazione "di inizializzazione deve completare normalmente"

mentre

class A{ 
{ 
    File f=new File("a"); 
    FileOutputStream fo=new FileOutputStream(f); 
    fo.write(3); 
} 
public A() throws IOException{ 
    // TODO Auto-generated constructor stub 
} 
} 

Questo codice non mostra alcuna fase di compilazione errore. Perché il codice precedente non viene compilato anche se ho dichiarato una clausola throws nel costruttore?

+0

Hai detto al blocco di inizializzazione di generare un'eccezione incondizionata, cos'altro ti aspetti? – skuntsel

risposta

4

Ci dovrebbe essere qualche condizione quando l'inizializzatore può effettivamente completare senza eccezioni.

Nel tuo caso non c'è modo che possa accadere.

Prova:

if(/*condition-to-fail*/) { 
    /*Not always, only when something is wrong. Compiler knows that.*/ 
    throw new FileNotFoundException(); 
} 

Aggiornamento:

La seguente dichiarazione è in realtà gettando l'eccezione.

throw new FileNotFoundException(); 

Quindi, senza condizioni, l'esecuzione del programma finisce sempre lì.

Mentre nella seguente -

FileOutputStream fo = new FileOutputStream(f); 

il costruttore FileOutputStream(File) non sempre buttare tale eccezione.

La clausola throws in public FileOutputStream(File file) throws FileNotFoundException sta solo dicendo che potrebbe generare quell'eccezione e lo farà solo se in fase di esecuzione il file non viene trovato altrimenti.

+0

+1 che funziona. ma perché abbiamo bisogno di avere un'affermazione condizionale? non si può semplicemente lanciare l'eccezione? – PermGenError

+2

@PremGenError: È come scrivere il codice dopo una dichiarazione di ritorno senza controllo delle condizioni. Anche il compilatore può rilevarlo, lo stesso in questo caso. –

+0

nice ... thanks :) – PermGenError

2

http://docs.oracle.com/javase/specs/jls/se7/html/jls-8.html#jls-8.6

It is a compile-time error if an instance initializer cannot complete normally

http://docs.oracle.com/javase/specs/jls/se7/html/jls-14.html#jls-14.21

A non-empty block that is not a switch block can complete normally iff the last statement in it can complete normally.

...

The if statement, whether or not it has an else part, is handled in an unusual manner. For this reason, it is discussed separately at the end of this section.

...

in order to allow the if statement to be used conveniently for "conditional compilation" purposes, the actual rules differ.

...

+0

+1 solo risposta che fornisce il motivo reale. – assylias

1

In primo compilatore caso è già sapendo che l'inizializzatore istanza è mai andare a completare normalmente perché avete esplicitamente gettato FileNotFoundException laggiù. Puoi dire che è la valutazione del codice intelligente del compilatore. Ma se si fa in modo che il compilatore creda che l'inizializzatore dell'istanza abbia anche una minima possibilità di completamento, il compilatore non si lamenterà durante la compilazione. Ad esempio nel codice fornito di seguito, sebbene il file IDonotexist.txt non esista nella mia directory e sono sicuro che genererebbe FileNotFoundException ma il compilatore continuerà a farlo compilare correttamente. Perché? Poiché l'esistenza del file viene verificata durante l'esecuzione del codice, non durante la compilazione.

class A 
{ 
    { 
     FileReader fr = new FileReader(new File("IDonotexist.txt")); 
    } 
    public A() throws IOException 
    { 
     // TODO Auto-generated constructor stub 
    } 
    public static void main(String st[])throws Exception 
    { 
     A a = new A(); 
    } 
} 

Questo è simile al caso di inizializzazione della variabile finale. Per esempio nel seguente codice, il compilatore mostrerà errore di compilazione

public void calling() 
    { 
     final int i; 
     int k = 90; 
     if (k == 90) 
     { 
      i = 56; 
     } 
     System.out.println(i);//Compiler will show error here as: variable i might not have been initialized 
    } 

Ma se i sostituire la condizione if (k == 90) con if(true) allora compilatore non mostrerà errore. Perché il compilatore ora sapendo che allo i verrà assegnato un certo valore.

Problemi correlati