Java String.valueOf(null)抛出NPE,但是对象a = null; String.valueOf(a)返回'null'

Mar*_*tus 36 java string

是否存在以下行为的逻辑语言设计类型解释(Java 7和我怀疑早期版本):

    Object  a = null;
    String as = String.valueOf(a);              // as is assigned "null"
    System.out.println(as+":"+as.length());     // prints: "null:4"
    System.out.println ( String.valueOf(null)); // NPE
Run Code Online (Sandbox Code Playgroud)

Tom*_*Tom 42

在语句中System.out.println(String.valueOf(null));有一个方法调用public static String valueOf(char data[]),源代码如下:

public static String valueOf(char data[]) {
  return new String(data);
}
Run Code Online (Sandbox Code Playgroud)

这就是你获得NPE的原因

另一方面,在语句中Object a = null; String as = String.valueOf(a);有一个方法调用public static String valueOf(Object obj),源代码如下:

public static String valueOf(Object obj) {
    return (obj == null) ? "null" : obj.toString();
}
Run Code Online (Sandbox Code Playgroud)

这就是为什么你得到"null"而不是NPE


Java语言规范中的一点理论:15.12.2.5选择最具体的方法

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

A char[]是类型Object,但不是所有Object类型char[].型char[]更具体的比对象和作为Java语言规范所描述的,String.valueOf(char[])过载被选择在这种情况下.

编辑

值得一提的是Ian Roberts提到的内容(在下面的评论中):

需要注意的是这是一个编译错误,如果没有一个统一的超载比所有其他更具体的是很重要的-如果有一个valueOf(String)方法,以及valueOf(Object)valueOf(char[])随后的非类型化的调用String.valueOf(null) 是不明确

  • 重要的是要注意,如果没有比其他所有更重要的单个重载,那么这是一个编译错误 - 如果有一个`valueOf(String)`方法以及`valueOf(Object)`和`valueOf(char [ ])`然后调用无类型的`String.valueOf(null)`将是不明确的. (6认同)

Avi*_*gal 15

第一次调用是String#valueOf(Object),第二次调用是String#valueOf(char[])

根据参数的静态类型选择重载方法,这就是第一个工作而秒获得NPE的原因.

如果你调用System.out.println ( String.valueOf((Object)null));它将工作

  • +1.值得一提的术语:根据参数*static type*选择重载方法. (2认同)

Buh*_*ndi 7

那是因为String课堂上的这段代码:

public static String valueOf(char data[]) {
return new String(data);
}
Run Code Online (Sandbox Code Playgroud)

你的代码(抛出NullPointerException)调用上面提到的方法,因此,data字段是null.实际上,这个调用是由String类在构造函数上抛出的.

使用JDK 6,例外情况如下:

java.lang.NullPointerException
    at java.lang.String.<init>(String.java:177)
    at java.lang.String.valueOf(String.java:2840)
    at org.bfs.data.SQLTexter.main(SQLTexter.java:364)
Run Code Online (Sandbox Code Playgroud)

至于你的行:

System.out.println(as+":"+as.length());     // prints: "null:4"
Run Code Online (Sandbox Code Playgroud)

这适用于以下方法:

public static String valueOf(Object obj) {
return (obj == null) ? "null" : obj.toString();
}
Run Code Online (Sandbox Code Playgroud)

显然,a类型是Object这样的String.valueOf(Object)方法被调用.

如果您特别想调用String.valueOf(Object obj)方法,请按如下方式对null进行类型转换:

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

您遇到了方法重载(其中有多个方法具有相同的名称和方法签名,但具有不同的方法参数).在您的情况下(发生NPE),JVM根据最具体的静态类型确定调用哪个方法.如果声明了类型,则最具体的方法是具有相同参数类型的声明变量的方法,否则,JVM使用最具体的方法规则来查找要调用的方法.

我希望这有帮助.