web-dev-qa-db-ja.com

String.valueOf(null)がNullPointerExceptionをスローするのはなぜですか?

ドキュメントによると、メソッド String.valueOf(Object obj) は以下を返します。

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

しかし、私がこれをしようとするとどうなります:

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

代わりにNPEをスローしますか? (信じない場合は自分で試してみてください!)

スレッド「メイン」の例外Java.lang.NullPointerException 
 at Java.lang.String。(Unknown Source)
 at Java.lang.String.valueOf(Unknown Source)

どうしてこれが起こっているのですか?ドキュメントは私に嘘をついていますか?これはJavaの大きなバグですか?

117
user282886

問題は、String.valueOfメソッドがoverloadedであることです:

Java仕様言語では、これらの種類の場合、最も具体的なオーバーロードを選択することが義務付けられています。

JLS 15.12.2.5最も具体的な方法の選択

複数のメンバーメソッドがアクセス可能で、メソッド呼び出しに適用できる場合、ランタイムメソッドディスパッチの記述子を提供するために1つを選択する必要があります。 Javaプログラミング言語は、最も限定的なメソッドが選択されるというルールを使用します。

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

String.valueOf(char[])は、配列がnull以外であると想定しています。この場合、nullが指定されているため、NullPointerExceptionをスローします。

簡単な「修正」は、次のようにnullObjectに明示的にキャストすることです。

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

関連する質問


この話の教訓

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

  • 有効なJava第2版、項目41:慎重にオーバーロードを使用する
    • 過負荷になる可能性があるからといって、毎回する必要があるという意味ではありません
    • 混乱を引き起こす可能性があります(特にメソッドが大きく異なる場合)
  • 優れたIDEを使用すると、コンパイル時にどのオーバーロードが選択されているかを確認できます
    • Eclipseを使用すると、上記の式にマウスを合わせると、indeedvalueOf(char[])オーバーロードが選択されていることがわかります。
  • null(従う例)を明示的にキャストしたい場合があります

こちらもご覧ください


キャスト中null

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

  • オーバーロードを選択するには(上記の例のように)
  • 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"

こちらもご覧ください

関連する質問

192

問題は、 String.valueOf(char[]) およびnotString.valueOf(Object)

その理由は、Javaは常に、提供されたパラメーターで機能するオーバーロードされたメソッドの最も具体的なバージョンを選択するからです。nullObjectパラメータですが、char[]パラメータの有効な値でもあります。

Java Objectバージョンを使用するには、変数を介してnullを渡すか、Objectへの明示的なキャストを指定します。

Object o = null;
System.out.println("String.valueOf(null) = " + String.valueOf(o));
// or
System.out.println("String.valueOf(null) = " + String.valueOf((Object) null));
16
Joachim Sauer

4867608 の番号が付けられたバグが2003年にこの方法で提出されましたが、この説明では「修正しない」として解決されました。

互換性の制約のため、これを変更することはできません。最終的に呼び出されるのはpublic static String valueOf(char data [])メソッドであり、null引数の「null」の置換については言及していないことに注意してください。

@ ###。### 2003-05-23

5
cbare