2012-11-28 5 views
49

Poiché ritengo sia una buona pratica di programmazione, creo tutte le variabili (locali o di istanza) final se sono destinate a essere scritte una sola volta.Assegnazione variabile finale con try/catch

Tuttavia, ho notato che quando un'assegnazione variabile può generare un'eccezione Non è possibile effettuare detto variabile finale:

final int x; 
try { 
    x = Integer.parseInt("someinput"); 
} 
catch(NumberFormatException e) { 
    x = 42; // Compiler error: The final local variable x may already have been assigned 
} 

C'è un modo per fare questo senza ricorrere a una variabile temporanea? (o non è questo il posto giusto per un modificatore finale?)

+1

Dubito che sia possibile farlo senza una variabile temporanea. – NPE

+8

'final int x = makeX();' sicuramente. (try-catch in function) –

+2

Shocking che il JDK [non ha ancora un 'tryParse'] (http://stackoverflow.com/questions/1486077/java-good-way-to-encapsulate-integer-parseint) . –

risposta

44

Un modo per fare ciò è introdurre una variabile temporanea (non final), ma hai detto che non volevi farlo.

Un altro modo è quello di spostare i due rami del codice in una funzione:

final int x = getValue(); 

private int getValue() { 
    try { 
    return Integer.parseInt("someinput"); 
    } 
    catch(NumberFormatException e) { 
    return 42; 
    } 
} 

Se questo è pratico dipende caso esatto uso.

Tutto sommato, purché x sia una variabile locale con scope appropriatamente, l'approccio generale più pratico potrebbe essere quello di non lasciare final.

Se, d'altra parte, x è una variabile membro, il mio consiglio sarebbe quello di utilizzare un non final temporanea durante l'inizializzazione:

public class C { 
    private final int x; 
    public C() { 
    int x_val; 
    try { 
     x_val = Integer.parseInt("someinput"); 
    } 
    catch(NumberFormatException e) { 
     x_val = 42; 
    } 
    this.x = x_val; 
    } 
} 
+0

Per un ambito locale sono d'accordo con te, tuttavia questo si verifica più spesso con variabili di istanza. – dtech

+0

Immagino che possa riflettere un errore non può fare un riferimento statico al metodo non statico getValue(), quindi supponiamo di usare la funzione statica, potrei sbagliarmi statico privato int getValue() .. @ NPE – gks

+0

Se this.x è un tipo di oggetto come Integer, quindi è necessario un po 'di più (purtroppo). Se si lascia x_val non dichiarato, il compilatore si lamenterà che potrebbe non essere stato inizializzato. Se il fallback per il blocco catch è nullo, è necessario eseguire la pre-inizializzazione su null e assegnare in modo ridondante null nel catch per chiarezza (che è la mia preferenza) o avere un catch vuoto. –

2

No, non è il posto giusto, immaginare che hai di più quindi 1 istruzione nel blocco try e catch, la prima dice: x = 42. Dopo alcune altre dichiarazioni il blocco try fallisce, e va al blocco catch, dove il tuo Saying x = 30. Ora hai definito x due volte.

+9

Il compilatore è abbastanza intelligente da sapere quali istruzioni lanciare quali eccezioni. Potrebbe non essere possibile in tutti i casi, ma proprio come il compilatore può dirvi in ​​alcuni casi sul codice morto, ecc. Dovrebbe essere in grado di capire se il finale funzionerebbe. – Stefan

+0

Per supportare ciò che @Stefan ha detto, Clang è in grado di capirlo quando compila Swift. –