2015-04-14 12 views
21

Z jakiegoś powodu, następujący kod kompiluje normalnie:Ternary wyrażenie niekiedy omija kontrole kompilatora walidacji

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

bym normalnie spodziewać Eclipse aby oznaczyć go jako błąd (null nie można zwrócił się do double prymitywne).

Wystarczy do tyłu moje założenie, ten kod nie zadziała:

public double getSomeDouble() { 
    return null; 
} 

Eclipse by zaznaczyć linię return null jako błędu, stwierdzając:

Niezgodność typów: nie można przekonwertować z null do double

Dlaczego nie jest napisane to samo w poprzednim fragmencie kodu ?!

+0

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

Odpowiedz

23

Jest to spowodowane autoboxing i autounboxing. Jeśli spojrzysz na kod bajtowy (poniżej), możesz zobaczyć połączenia z Double.valueOf (boxing the 3.7d) i Double#doubleValue (rozpakowywanie wyniku wyrażenia warunkowego). Argumenty do operatora warunkowego musi być tego samego typu, więc kompilator jest skutecznie odwracając swój kod na to:

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

... bo Double jest najbardziej rozpowszechnionym typem specyficzny może znaleźć dla 3.7d i null.

użyłem argumentu ciąg (w celu wyeliminowania optymalizacji kompilatora wokół niezmiennego wyrazu "" != null, które kompilator będzie w stanie powiedzieć, że nigdy nie było prawdziwe):

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

które skutecznie staje:

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

... i rzeczywiście uzyskałem NPE w czasie pracy, gdy zdałem null dla str, kiedy próbowałem zadzwonić pod numer doubleValue() pod numerem null.

Oto kod bajtowy dla mojego getSomeDouble(String) (od javap -c MyClass): [? Podobne]

 
    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

Choć powodem błędu jest teraz jasne, że nadal chciałbym skonfigurować kompilator Eclipse śledzić te dla mnie nie (w czasie, który jest zbyt późno :(), znasz sposób? –

+2

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

+0

@MaximRahlis: Obawiam się, że nie. Wygląda na to, że Guillaume znalazł żądanie funkcji, które możesz chcieć obejrzeć ... –