为什么String.valueOf(null)抛出NullPointerException?

use*_*886 122 java null api-design overloading nullpointerexception

根据文档,该方法String.valueOf(Object obj)返回:

如果参数是null,那么一个字符串等于"null"; 否则,obj.toString()返回值.

但是当我尝试这样做时怎么样:

System.out.println("String.valueOf(null) = " + String.valueOf(null));
Run Code Online (Sandbox Code Playgroud)

它会引发NPE而不是?(如果你不相信,请亲自尝试!)

    Exception in thread "main" java.lang.NullPointerException
    at java.lang.String.(Unknown Source)
    at java.lang.String.valueOf(Unknown Source)

怎么会发生这种情况?文档对我说谎吗?这是Java中的一个主要错误吗?

pol*_*nts 196

问题是该String.valueOf方法是重载的:

Java Specification Language规定在这种情况下,选择最具体的重载:

JLS 15.12.2.5选择最具体的方法

如果多个成员方法都可访问并适用于方法调用,则必须选择一个为运行时方法调度提供描述符.Java编程语言使用选择最具体方法的规则.

A char[] 是-a Object,但不是全部Object 是-a char[].因此,char[]更具体的Object,和由Java语言指定,String.valueOf(char[])超载被选择在这种情况下.

String.valueOf(char[])期望数组是非数组null,并且null在这种情况下给出,然后它会抛出NullPointerException.

简单的"修复"是将null显式转换Object为如下:

System.out.println(String.valueOf((Object) null));
// prints "null"
Run Code Online (Sandbox Code Playgroud)

相关问题


故事的道德启示

有几个重要的:

  • 有效的Java第2版,第41项:明智地使用重载
    • 仅仅因为你可以超负荷,并不意味着每次都应该
    • 它们会引起混淆(特别是如果方法做了截然不同的事情)
  • 使用好的IDE,您可以检查在编译时选择了哪个重载
    • 使用Eclipse,您可以鼠标悬停在上面的表达式上,看看确实valueOf(char[])选择了重载!
  • 有时您想要显式转换null(示例要遵循)

也可以看看


在铸造 null

至少有两种情况需要明确地转换null为特定的引用类型:

  • 选择重载(如上例所示)
  • nullvararg参数作为单个参数

后者的一个简单示例如下:

static void vararg(Object... os) {
    System.out.println(os.length);
}
Run Code Online (Sandbox Code Playgroud)

然后,我们可以有以下内容:

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

vararg((Object) null);    // prints "1"
Run Code Online (Sandbox Code Playgroud)

也可以看看

相关问题

  • 另一个建议:当你重载一个方法并且可以在两个重载上调用一个参数时(例如在这种情况下为`null`),请确保两个重载对于该值的作用相同! (5认同)
  • @Joachim:我刚刚阅读了这个项目,并惊喜地发现这两种方法都被明确讨论过了!布洛赫更进了一步,并声称因为`String.valueOf(Object)`和`valueOf(char [])`做了完全不同的事情(无论是否为'null`),也许它们不应该是重载的第一名. (3认同)

Joa*_*uer 17

问题是你在打电话String.valueOf(char[])不是 String.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));
Run Code Online (Sandbox Code Playgroud)


cba*_*are 5

在2003年以这种方式提交了一个编号为4867608的错误,该错误被解决为"无法解决"此解释.

由于兼容性限制,我们无法更改此设置.请注意,它是公共静态字符串valueOf(char data [])方法,最终被调用,并且没有提到为null参数替换"null".

@ ###.### 2003-05-23