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

标签 java null nullpointerexception overloading api-design

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

if the argument is null, then a string equal to "null"; otherwise, the value of obj.toString() is returned.

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

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 的主要错误吗?

最佳答案

问题是 String.valueOf 方法被重载:

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

JLS 15.12.2.5 Choosing the Most Specific Method

If more than one member method is both accessible and applicable to a method invocation, it is necessary to choose one to provide the descriptor for the run-time method dispatch. The Java programming language uses the rule that the most specific method is chosen.

一个char[] is-an Object,但不是所有Object is-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"

相关问题


故事的寓意

有几个重要的:

  • Effective Java 第 2 版,第 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"

另见

相关问题

关于java - 为什么 String.valueOf(null) 会抛出 NullPointerException?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3131865/

相关文章:

java - 这个nullPointerException的原因是什么?

java - 什么是NullPointerException,我该如何解决?

java - 如何在JSch中使用SFTP channel 执行shell命令?

java - 如何在 mac 上运行 sonarqube?

java - 如何使用 java 将 UTF16(表情符号)转换为 HTML 实体(十六进制)

java - 查询id返回类型

r - R 中是否有一种优雅的方法可以跳过空元素的 for 循环?

Android Sqlite 添加列后根据条件选择条目

asp.net - 在 ASP.net Bind() 调用上测试空值、内联

android - 指令 'monitor-enter v1' 期间出现空指针异常