1. ホーム
  2. java

[解決済み] String.valueOf(null)がNullPointerExceptionをスローするのはなぜですか?

2022-07-01 05:31:11

質問

ドキュメントによると String.valueOf(Object obj) が返します。

もし引数が null と等しい文字列を返します。 "null" それ以外の場合は obj.toString() の値が返されます。

しかし、私はこれを行うしようとすると、なぜです。

System.out.println("String.valueOf(null) = " + String.valueOf(null));

を実行すると、代わりにNPEを投げるのですか?(信じられないなら自分で試してみてください!)

    スレッド "main" java.lang.NullPointerException で例外が発生しました。
    at java.lang.String.(ソース不明)
    at java.lang.String.valueOf(提供元不明)

どうしてこんなことが起こるのでしょうか?ドキュメントが嘘をついているのでしょうか?これはJavaの大きなバグなのでしょうか?

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

この問題は String.valueOf メソッドが オーバーロード :

Java 仕様言語では、このような場合、以下のように義務付けられています。 最も具体的なオーバーロード が選択されます。

JLS 15.12.2.5 最も具体的な方法を選択する

複数のメンバメソッドがメソッド呼び出しにアクセス可能かつ適用可能である場合、実行時メソッドディスパッチ用の記述子を提供するために1つを選択することが必要です。Javaプログラミング言語では 最も具体的な メソッドが選択されます。

A char[] Object であり、すべてではありませんが Object char[] . したがって char[] より具体的 よりも Object であり、Java 言語で指定されているように String.valueOf(char[]) のオーバーロードがこの場合選択されます。

String.valueOf(char[]) は、配列が非表示であることを期待します。 null であることを期待し、また null が指定されている場合は NullPointerException .

簡単な修正は null に明示的にキャストすることです。 Object を以下のように変更します。

System.out.println(String.valueOf((Object) null));
// prints "null"

関連する質問


物語のモラル

重要なものがいくつかあります。

  • Effective Java 第2版、項目41:オーバーロードを賢く使う
    • オーバーロードが可能だからといって、毎回オーバーロードする必要はありません。
    • 混乱を招く可能性がある (特にメソッドが全く異なることを行う場合)
  • 優れた IDE を使用すると、コンパイル時にどのオーバーロードが選択されたかを確認できます。
    • Eclipseでは、上記の式にマウスを乗せると 確かに と表示されます。 valueOf(char[]) のオーバーロードが選択されています!
  • 時には、明示的にキャストしたい null を明示的にキャストしたい場合があります (後述する例)。

こちらもご覧ください


キャストについて null

少なくとも二つの状況において、明示的に null を特定の参照型にキャストすることが必要な状況が少なくとも二つあります。

  • オーバーロードを選択する場合(上記の例で与えられたように)
  • 以下のように null を vararg パラメータへの単一引数として与える。

後者の簡単な例として、以下のようなものがあります。

static void vararg(Object... os) {
    System.out.println(os.length);
}

とすれば、以下のようになります。

vararg(null, null, null); // prints "3"
vararg(null, null);       // prints "2"
vararg(null);             // throws NullPointerException!

vararg((Object) null);    // prints "1"

こちらもご覧ください

関連する質問