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


127

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

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

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

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

它会抛出NPE吗?(如果您不相信,请自己尝试!)

    线程“主”中的异常java.lang.NullPointerException
    在java.lang.String。(未知来源)
    在java.lang.String.valueOf(未知来源)

怎么会这样呢?文件在骗我吗?这是Java中的主要错误吗?

Answers:


201

问题是String.valueOf方法已重载

Java规范语言要求在这种情况下,选择最具体的重载

JLS 15.12.2.5选择最具体的方法

如果可以访问多个成员方法并将其应用于方法调用,则必须选择一个成员方法来为运行时方法分派提供描述符。Java编程语言使用选择最特定方法的规则。

一个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"

相关问题


故事的道德启示

有几个重要的方面:

  • 有效的Java 2nd Edition,项目41:明智地使用重载
    • 仅仅因为您可以超载,并不意味着您每次都应该
    • 它们会引起混乱(尤其是如果方法做的事情截然不同的话)
  • 使用良好的IDE,您可以检查在编译时选择了哪个重载
    • 使用Eclipse,您可以将鼠标悬停在上面的表达式上,并看到确实valueOf(char[])选择了重载!
  • 有时您想显式投射null(以下示例)

也可以看看


铸造时 null

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

  • 选择重载(如上例所示)
  • 为了给null作为单个参数的可变参数参数

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

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"

也可以看看

相关问题


5
另一个建议:当您重载一个方法并且可能在两个重载上调用一个参数时(例如null在本例中),请确保两个重载在该值上的作用相同!
Joachim Sauer 2010年

3
@Joachim:我刚刚阅读了这篇文章,并惊喜地发现这两种方法得到了明确讨论!Bloch进一步走了一步,声称既然String.valueOf(Object)valueOf(char[])无论如何都做完全不同的事情(不管是否这样做null),也许它们首先不应该是过载。
polygenelubricants 2010年

有一个问题...如果您有一个返回Object的方法,则该语句return null;将与return (Object) null;?完全相同。
user972276

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));

5

早在2003年就以这种方式提交了编号为4867608的错误,并通过此解释被解决为“无法修复”。

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

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


By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.