Object obj = null;
System.out.println(String.valueOf(obj));
System.out.println(String.valueOf(null));
第一句可以打印出null,但是第二句报空指针异常。
造成这种区别的原因在于两者选取了不同的重载方法。
Java的重载过程分两个阶段。
第一阶段选取所有可获得并且可应用的方法或构造器。看一下String.valueOf()源码,有以下几个重载方法可供选择:
String valueOf(Object obj) //①
String valueOf(char data[]) //②
String valueOf(boolean b)
String valueOf(char c)
...
因为基本类型不能赋于 null,所以可供选择的方法只有 valueOf(char data[]) 和 valueOf(Object obj)。
第二阶段在第一阶段选取的方法或构造器中选取最精确的一个,如果一个方法或构造器可以接受传递给另一个方法或构造器的任何参数,那么我们就说第一个方法比第二个方法缺乏精确性。方法 valueOf(Object obj) 可以接收任何传给 valueOf(char data[]) 的参数,我们说方法 valueOf(Object obj) 相对方法 valueOf(char data[]) 缺乏精确性,所以在重载时会选择方法valueOf(char data[])。
对于构造方法1
public static String valueOf(Object obj) {
return (obj == null) ? "null" : obj.toString();
}
显然会直接返回“null”
对于构造方法2
public static String valueOf(char data[]) {
return new String(data);
}
再看对应的String构造方法:
public String(char value[]) {
this.offset = 0;
this.count = value.length; //※
this.value = StringValue.from(value);
}
运行到※处时,会抛出空指针异常。
如果将调用代码修改如下:
value = String.valueOf((Object)null);
重载时将会选择valueOf(Object obj)方法,就能回避这个异常。
这里要特殊强调下 String.valueOf(char[] list); 中 char[] 类型的特殊
下图是源码中的程序
从源码我们可以知道,尽管 list 是一个引用,但我们并不能把 list 看成一个 Object 对象引用,如果传递一个 null 给 list ,程序会在 执行 String。valueOf() r输出打印之前,先去将 null 转换成字符串 null,这就变成了上述第二种情况 String.valueOf(null),会直接报空指针异常