36

以下行为是否有逻辑语言设计类型的解释(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
4

3 回答 3

43

在语句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 选择最具体的方法

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

Achar[]是 type Object,但不是所有Object都是 type char[]。Typechar[]比Object更具体,如 Java 语言规范中所述,String.valueOf(char[])在这种情况下选择重载。

编辑

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

重要的是要注意,如果没有比所有其他重载更具体的单个重载,这是一个编译错误 - 如果有一个valueOf(String)方法以及valueOf(Object)然后 valueOf(char[])对无类型的调用String.valueOf(null) 将是模棱两可的

于 2013-01-02T15:16:36.020 回答
15

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

重载方法是根据参数的静态类型选择的,这就是为什么第一个有效而第二个获得 NPE 的原因。

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

于 2013-01-02T15:15:59.810 回答
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使用最具体的方法规则来查找调用哪个方法。

我希望这有帮助。

于 2013-01-02T15:13:47.983 回答