2015-04-14 13 views
21

Per qualche ragione, il seguente codice viene compilato normalmente:espressione ternario volte bypassa compilatore controlla convalide

public double getSomeDouble() { 
    return "" != null ? 3.7d : null; 
} 

io normalmente aspettare Eclipse a segnare come un errore (null non può essere acceso a un double primitivo).

Proprio per sostenere la mia ipotesi, questo codice non funzionerebbe:

public double getSomeDouble() { 
    return null; 
} 

Eclipse sarebbe segnare la linea return null come errore, affermando:

Tipo non corrispondente: non può convertire da null a double

Perché non dice la stessa cosa nello snippet di codice precedente ?!

+0

(http://stackoverflow.com/q/8098953/1391249) – Tiny

risposta

23

È dovuto a autoboxing e autounboxing. Se si guarda il bytecode (sotto), è possibile vedere le chiamate a Double.valueOf (boxing il 3.7d) e Double#doubleValue (unboxing il risultato dell'espressione condizionale). Gli operandi per l'operatore condizionale devono essere dello stesso tipo, in modo che il compilatore è effettivamente trasformando il codice in questo modo:

public double getSomeDouble() { 
    return ("" != null ? Double.valueOf(3.7d) : null).doubleValue(); 
} 

... perché Double è il tipo comune più specifica si possono trovare per 3.7d e null.

ho usato un argomento stringa (per eliminare ottimizzazione del compilatore attorno all'espressione invariante "" != null, che il compilatore in grado di dire non sarebbe mai stato vero):

public double getSomeDouble(String str) { 
    return str != null ? 3.7d : null; 
} 

che diventa efficace:

public double getSomeDouble(String str) { 
    return (str != null ? Double.valueOf(3.7d) : null).doubleValue(); 
} 

... e in effetti ho ottenuto un NPE in fase di esecuzione quando sono passato in null per str, quando ha provato a chiamare doubleValue() su null.

Ecco il bytecode per il mio getSomeDouble(String) (da javap -c MyClass): [? Related]

 
    public double getSomeDouble(java.lang.String); 
    Code: 
     0: aload_1 
     1: ifnull  13 
     4: ldc2_w  #7     // double 3.7d 
     7: invokestatic #9     // Method java/lang/Double.valueOf:(D)Ljava/lang/Double; 
     10: goto   14 
     13: aconst_null 
     14: invokevirtual #10     // Method java/lang/Double.doubleValue:()D 
     17: dreturn 
+4

Anche se la causa dell'errore è chiaro ora, vorrei ancora installare il compilatore di eclipse per tracciare quelli per me non (in runtime che è troppo tardi :(), sai di un modo? –

+2

https://bugs.eclipse.org/bugs/show_bug.cgi?id= 163065 – Guillaume

+0

@MaximRahlis: temo di no. Sembra che Guillaume abbia trovato una richiesta di funzionalità che potresti voler vedere ... –