この割り当てによってNPEが発生するのはなぜですか? 質問する

この割り当てによってNPEが発生するのはなぜですか? 質問する
public class Npe {
    static class Thing {
        long value;
    }

    public static Map<Thing, Long> map;

    public static void main(String[] args) {
        Thing thing = new Thing();
        method(null); // returns -1
        method(thing); // returns 0
        map = new HashMap<Thing, Long>();
        method(null); // returns -1
        method(thing); // NullPointerException thrown inside this method call
    }

    public static long method(Thing thing) {
        if (thing == null) {
            return -1;
        }
        Long v = (map == null) ? thing.value : map.get(thing); // NPE here
        if (v == null) {
            v = thing.value;
        }
        return v;
    }
}

の4回目の呼び出しで、内の指定された行に がスローされますmethod()。その行をNullPointerExceptionmethod()

Long v = (map == null) ? thing.value : map.get(thing);

Long v;
if (map == null) {
    v = thing.value;
} else {
    v = map.get(thing);
}

結果は「いいえ」NullPointerExceptionで、メソッドは期待どおりに動作します。問題は、「なぜ?」です。

?コンパイラは、演算子の結果が であると想定して、 への呼び出しの結果( を返して をスローする可能性がある)longを自動的にアンボックス化( から に降格)してLongいるように見えます。私見では、演算子の結果が であると想定して、代わりにオートボックス化(に昇格)するべきです。longmap.get(thing)nullNullPointerException?LonglongLongthing.value

さらに良いのは、次のステートメントをリファクタリングすることです。

Long v = (map == null) ? thing.value : map.get(thing);

これに(明示的longにキャストLong):

Long v = (map == null) ? (Long)thing.value : map.get(thing);

私のIDE(IntelliJ)はキャストが冗長であると表示しますが、コンパイルされたコードは期待どおりに動作し、NullPointerException!をスローしません。:-D

ベストアンサー1

条件式を検討してください:

(map == null) ? thing.value : map.get(thing)

longの型thing.valueが であるため、その式の結果は になりますlongJLS §15.25 - 条件演算子JLS 8 の表は素晴らしい追加機能です。さまざまな入力タイプに対して可能なすべての出力タイプを明確にします。条件式のタイプに関連する混乱が非常に多かったのです。

このメソッドを次のように呼び出すと、

method(thing);

mapではないので、式のnull条件は と評価され、次に と評価されて結果が取得されます。map == nullfalsemap.get(thing)

にはまだエントリがないのでmapmap.get(thing)は を返しますnull。しかし、結果の型は なのでlong、 に対してアンボックス化操作が実行されnull、が返されますNPE


thing.valueここで、 を明示的に にキャストするとLong、式の型は になりますLong。したがって、 の結果に対してアンボックス化は実行されずmap.get(thing)nullに割り当てられますLong v

おすすめ記事