2012-10-17 9 views
5

Questo è il frammento di codice in linguaggio Java:Branching che non può essere visto da compilatore

public void name(){ 
int value = 9; 
int o; 
if(value > 9) 
o = 5; 

if(value <= 9) 
o = 8; 

System.out.println(o); 
} 

Perché compilatore non può vedere la seconda istruzione if considerando l'ultima opzione del valore? Non verrà compilato. migliori saluti

+3

L'errore è: variabile o potrebbe non essere stata inizializzata (System.out.println (o)) –

+2

Perché sono due istruzioni if ​​invece di un if..else? – CBredlow

+0

Sto solo esplorando la lingua. Non vi è alcun motivo speciale per le due dichiarazioni if. – uml

risposta

5

Il compilatore deve trattare value mutevole a meno che non si dice il contrario. Dichiarandolo finalfixes the problem:

public void name(){ 
    final int value = 9; 
    int o; 
    if(value > 9) o = 5; 
    if(value <= 9) o = 8; 
    System.out.println(o); 
} 
+0

Sono sorpreso che non si possa facilmente supporre che sia immutabile in questo scenario –

+1

@BrianAgnew Posso solo supporre che il compilatore non sia autorizzato a trattare le due letture di 'value' nei due' if's come accedere allo stesso valore (e quindi rendendo le due condizioni complementari). – dasblinkenlight

+1

Il compilatore può operare solo su espressioni costanti durante il controllo dell'assegnazione definitiva. Né "valore> 9" né "valore <= 9" sono espressioni costanti a meno che "valore" sia una variabile costante che è essenzialmente una variabile "finale". – pingw33n

0

durante la compilazione:

Il compilatore vede che non avete inizializzato la variabile 'o' e si stampa nella sysout.

è possibile raggiungere questo obiettivo:

public void name(){ 
int value = 9; 
int o; 
if(value > 9) 
o = 5; 

else 
o = 8; 

System.out.println(o); 
} 
0

inizializzazione o prima, se le dichiarazioni dopo si dichiara

o=0; 
0

Come per JLS (§16) ogni campo variabile e non vuota locale devono essere definitivamente assegnati prima che possa essere Usato. Il compilatore esegue alcune analisi statiche di base per assicurarlo.

L'idea alla base dell'assegnazione definita è che un'assegnazione alla variabile locale o al campo finale vuoto deve avvenire su ogni possibile percorso di esecuzione dell'accesso. Allo stesso modo, l'idea alla base della non assegnazione definitiva è che nessun'altra assegnazione alla variabile finale vuota è consentita per verificarsi su qualsiasi percorso di esecuzione possibile a un incarico.

L'analizzatore statico può solo dedurre i valori delle espressioni costanti ($15.28) che non è il caso nel tuo esempio.

1

Il motivo per cui la versione originale non viene compilata è che le regole di "assegnazione definita" di JLS in JLS section 16 affermano che lo o non è stato assegnato definitivamente. Il compilatore segnala questo con un messaggio enigmatico che dice che "o potrebbe non essere stato inizializzato".

Ora, chiunque abbia una semplice capacità deduttiva può vedere che la seconda condizione if è la negazione della 1a condizione if, e quindi la variabile verrà sempre inizializzata. Tuttavia, il JLS non consente a un compilatore di effettuare tale detrazione. Il JLS dice che si tratta di un errore ...

Ci sono diversi modi per risolvere questo problema. Ad esempio

  • Assegnare qualcosa a o nella dichiarazione.
  • Sostituire le due istruzioni if con una singola dichiarazione if/else.
  • Declare value come final.

L'ultima correzione è interessante.La ragione per cui funziona è che le regole di assegnazione definite JLS richiedono al il compilatore di prendere in considerazione il valore di una costante con valore booleano costante in fase di compilazione.

Questa dichiarazione (con l'aggiunta final)

final int value = 9; 

significa che value è una costante in fase di compilazione. Ciò significa che value <= 9 e value > 9 sono anche costanti in fase di compilazione. Le regole di assegnazione definitiva JLS affermano quindi che o è sicuramente assegnato dopo

if(value <= 9) o = 8; 

e può essere utilizzato in seguito senza un errore di compilazione.


Le regole di assegnazione definiti hanno lo scopo di impedire l'uso di variabili non inizializzate, e prevenire vuote final variabili essere inizializzate più di una volta.

Il trattamento conservativo di JLS dei valori di espressione nelle regole di assegnazione definite è progettato per evitare problemi in cui un compilatore Java deduce che qualcosa è definitivamente assegnato, ma un altro non può. La sottocarena di espressioni costanti in fase di compilazione può essere gestita semplicemente valutando l'espressione e le regole JLS lo riconoscono implicitamente.

Problemi correlati