web-dev-qa-db-ja.com

三項演算子で不要なNullPointerExceptionを取得する-なぜですか?

次のコードの実行中に、行でNullPointerExceptionを取得しています:

_value = condition ? getDouble() : 1.0;
_

以前の行でgetDouble()の代わりにnullを使用すると、すべてが機能し、これは奇妙です。

_public class Test {
    static Double getDouble() {
        return null;
    }

    public static void main(String[] args) {
        boolean condition = true;
        Double value;

        value = condition ? null : 1.0;         //works fine
        System.out.println(value);              //prints null

        value = condition ? getDouble() : 1.0;  //throws NPE
        System.out.println(value);
    }
}
_

誰かがこの行動を理解するのを助けることができますか?

48
Joker

書くとき

_value = condition ? null : 1.0;
_

_condition ? null : 1.0_の型は参照型である必要があるため、型はDoubleであり、値nullを保持できます。

書くとき

_value = condition ? getDouble() : 1.0;
_

getDouble()nullを返します。これは次の記述と同等です。

_value = condition ? ((Double) null) : 1.0;
_

この場合、コンパイラはDoubledoubleを三項条件演算子の2番目と3番目の引数として認識し、式のタイプがdoubleであると決定します。したがって、nulldoubleに展開し、NullPointerExceptionを取得します。

条件付き三項演算子のタイプは、 JLS 15.25 のいくつかのテーブルによって決定されます。

第2および第3オペランドがnullおよびdoubleである場合、条件式のタイプはDoubleおよびnullの最小上限、つまりDouble

第2および第3オペランドがDoubleおよびdoubleの場合、条件式のタイプはdoubleです。

77
Eran

#jls-15.25 を参照してください:

enter image description here

第2オペランドがDoubleであり、第3オペランドがdoubleである場合、結果は次のようになります。

getCount() == 1 ? getDouble() : 1.0

doubleになります。

そして、_Double null_(getDouble()によって返される)をdoubleに変換しようとすると、NPEがスローされます。

23
xingbin