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

时间:2013-01-02 15:11:27

标签: 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

3 个答案:

答案 0 :(得分:42)

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

public static String valueOf(char data[]) {
  return new String(data);
}

这就是为什么你得到 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();
}

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


Java语言规范的一些理论:15.12.2.5 Choosing the Most Specific Method

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

char[]类型为Object,但并非所有Object都属于char[]类型。类型char[] 比Object更具体,并且如Java语言规范中所述,在这种情况下选择了String.valueOf(char[])重载。

修改

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

  

重要的是要注意,如果没有单一的,那就是编译错误   超载比所有其他更具体 - 如果有的话   valueOf(String)方法以及valueOf(Object)和。{   valueOf(char[])然后调用无类型的String.valueOf(null)   会不明确的

答案 1 :(得分:15)

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

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

如果您调用System.out.println ( String.valueOf((Object)null));,它将起作用

答案 2 :(得分:7)

这是因为String类中的代码:

public static String valueOf(char data[]) {
return new String(data);
}

您的代码(抛出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)

关于你的专栏:

System.out.println(as+":"+as.length());     // prints: "null:4"

这适用于以下方法:

public static String valueOf(Object obj) {
return (obj == null) ? "null" : obj.toString();
}

显然,a的类型为Object,因此会调用String.valueOf(Object)方法。

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

System.out.println (String.valueOf((Object)null));

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

我希望这会有所帮助。