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

问题

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

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

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

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

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

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

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


#1 热门回答(176 赞)

问题是String.valueOf方法isoverloaded:

  • String.valueOf(Object)
  • String.valueOf(char [])

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

JLS 15.12.2.5选择最具体的方法

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

Achar[]is-anObject,但不是全部Objectis-achar[]。因此,char[]中心特定于Object,并且在Java语言中指定,在这种情况下选择了String.valueOf(char[])overload。

String.valueOf(char[])将数组视为非null,并且在这种情况下给出了null,然后它抛出了NullPointerException

简单的"修复"是将433367316明确地转换为Object如下:

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

###相关问题

  • 多态模糊区分如何工作?
  • 在Java中为null选择哪个重载?

故事的道德启示

有几个重要的:

  • 有效的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"

也可以看看

  • Java语言指南/ varargs - 了解它是如何实现的

###相关问题

  • 为什么空投?
  • 形式参数类型声明中double ...和double []之间的差异

#2 热门回答(13 赞)

问题是你打电话String.valueOf(char[])而不是String.valueOf(Object)

这样做的原因是Java将始终选择与提供的参数一起使用的重载方法的最具体版本.null是aObject参数的有效值,但它也是achar[]参数的有效值。

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

#3 热门回答(5 赞)

一个错误,编号为4867608,于2003年以这种方式提交,经解释为"无法解决"此解释。

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