1. ホーム
  2. java

[解決済み] Boolean.valueOf()でNullPointerExceptionが発生することがある。

2022-05-18 02:56:14

質問

このようなコードがあります。

package tests;

import java.util.Hashtable;

public class Tests {

    public static void main(String[] args) {

        Hashtable<String, Boolean> modifiedItems = new Hashtable<String, Boolean>();

        System.out.println("TEST 1");
        System.out.println(modifiedItems.get("item1")); // Prints null
        System.out.println("TEST 2");
        System.out.println(modifiedItems.get("item1") == null); // Prints true
        System.out.println("TEST 3");
        System.out.println(Boolean.valueOf(null)); // Prints false
        System.out.println("TEST 4");
        System.out.println(Boolean.valueOf(modifiedItems.get("item1"))); // Produces NullPointerException
        System.out.println("FINISHED!"); // Never executed
    }
}

私の問題は、なぜ テスト 3 は正常に動作しています (それは false を出力し NullPointerException を生成しない)一方 テスト4 を投げる。 NullPointerException . テストを見ればわかるように 1 2 , nullmodifiedItems.get("item1") はイコールであり null .

Java 7と8で動作は同じです。

どのように解決するのですか?

どのオーバーロードが呼び出されるかを注意深く見る必要があります。

  • Boolean.valueOf(null) Boolean.valueOf(String) . これは NPE を投げません。
  • Boolean.valueOf(modifiedItems.get("item1")) Boolean.valueOf(boolean) というのは modifiedItems の値は Boolean であり,アンボクシングの変換が必要である。このため modifiedItems.get("item1")null であるならば、その値のアンボックスである。 Boolean.valueOf(...) - ではなく、その値のアンボックスであり、NPEをスローします。

どのオーバーロードが呼び出されるかを決定するためのルールは かなり毛深い ですが、おおよそ次のようなものです。

  • 最初のパスでは、ボックス化/アンボックス化(可変アリティメソッドも)を許可せずに、メソッドのマッチングを検索します。

    • なぜなら null は許容される値であり String は許容範囲ですが boolean , Boolean.valueOf(null) にマッチするのは Boolean.valueOf(String) にマッチします。
    • Boolean はどちらも許容範囲外です。 Boolean.valueOf(String) または Boolean.valueOf(boolean) であるため、このパスではどのメソッドにもマッチしません。 Boolean.valueOf(modifiedItems.get("item1")) .
  • 2 番目のパスでは、メソッドの一致が検索され、ボックス化/アンボックス化が可能になります (ただし、可変アリティのメソッドはまだできません)。

    • A Boolean はボックスが解除され boolean というように Boolean.valueOf(boolean) にマッチするのは Boolean.valueOf(modifiedItems.get("item1")) にマッチします。しかし、これを呼び出すには、コンパイラによって 箱詰め解除の変換が挿入されなければなりません。 Boolean.valueOf(modifiedItems.get("item1").booleanValue())
  • (可変アリティメソッドを許可する3つ目のパスがありますが、最初の2つのパスがこれらのケースにマッチしているので、ここでは関係ありません)