为什么 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

问题是方法重载:String.valueOf

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

JLS 15.12.2.5 选择最具体的方法

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

A an,但不是所有的 is-a 。因此, 比 更具体,并且根据 Java 语言的指定,在这种情况下选择重载。char[]ObjectObjectchar[]char[]ObjectString.valueOf(char[])

String.valueOf(char[])期望数组是 non-,并且由于在本例中给出了,因此它抛出 。nullnullNullPointerException

简单的“修复”是显式地将 转换为 如下所示:nullObject

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

相关问题


故事的寓意

有几个重要的:

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

另请参见


关于铸造null

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

  • 选择重载(如上例所示)
  • 将单个参数提供给 vararg 参数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"

另请参见

相关问题


答案 2

问题是你调用的是 String.valueOf(char[]) 而不是 String.valueOf(Object)。

这样做的原因是,Java将始终选择使用所提供参数的重载方法的最特定版本。 是参数的有效值,但它也是参数的有效值。nullObjectchar[]

要使 Java 使用该版本,请通过变量传入或指定显式强制转换为 Object:Objectnull

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