2015-04-14 2 views
21

По какой-то причине, следующий код компилируется нормально:троичного выражения иногда обходит компилятор проверяет валидации

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

я обычно ожидать Eclipse, чтобы пометить его как ошибку (null не может быть повернут к double примитиву).

Просто поддержать мое предположение, этот код не будет работать:

public double getSomeDouble() { 
    return null; 
} 

Затмение будет означать return null линию как ошибку, заявив:

Несоответствие типа: не может конвертировать из null в double

Почему он не говорит то же самое в предыдущем фрагменте кода ?!

+0

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

ответ

23

Это связано с autoboxing и autounboxing. Если вы посмотрите на байт-код (см. Ниже), вы можете позвонить по номеру Double.valueOf (бокс 3.7d) и Double#doubleValue (распаковка результата условного выражения). Операнды к условному оператору должен быть того же типа, так что компилятор эффективно превращая ваш код в это:

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

... потому что Double наиболее специфичен распространенный тип он может найти для 3.7d и null.

Я использовал строковый аргумент (для устранения оптимизации компилятора вокруг инвариантного выражения "" != null, что компилятор смог бы сказать, никогда не будет правдой):

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

, который эффективно становится:

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

... и действительно получил NPE во время работы, когда я прошел в null для str, когда он пытался позвонить doubleValue() по телефону null.

Вот байткод для моего getSomeDouble(String) (от javap -c MyClass): [? Относящиеся]

 
    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

Хотя причина ошибки теперь ясно, я все еще хотел бы настроить компилятор eclipse, чтобы отслеживать это для меня нет (во время выполнения это слишком поздно :(), знаете ли вы о способе? –

+2

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

+0

@MaximRahlis: Боюсь, что нет. Похоже, что Guillaume нашел запрос на функцию, который вы, возможно, захотите посмотреть ... –

Смежные вопросы