是否存在针对以下行为的逻辑语言设计类型解释(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
答案 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[]
修改强>
值得一提的是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使用最具体的方法规则来查找要调用的方法。
我希望这会有所帮助。