public class TestString {
public static void main(String[] args) {
Object obj = null;
// 输出 "null" 字符串,不是空对象 null,也不是空字符串 ""
System.out.println(String.valueOf(obj));
// 抛出空指针异常
System.out.println(String.valueOf(null));
}
}
下面来分析分析原因。
第一个的源码实现:
/**
* Returns the string representation of the <code>Object</code> argument.
*
* @param obj an <code>Object</code>.
* @return if the argument is <code>null</code>, then a string equal to
* <code>"null"</code>; otherwise, the value of
* <code>obj.toString()</code> is returned.
* @see java.lang.Object#toString()
*/
public static String valueOf(Object obj) {
return (obj == null) ? "null" : obj.toString();
}
源码很简单,如果对象为空,就返回字符串的"null"...不为空就调用toString方法。
第二个和第一个的不同,是 java 对重载的不同处理导致的。
基本类型不能接受 null 入参,所以接受入参的是对象类型,如下两个:
String valueOf(Object obj)
String valueOf(char data[])
这两个都能接受 null 入参,这种情况下,Java 的重载会选取其中更精确的一个,所谓精确就是,重载方法 A 和 B,如果方法 A 的入参是 B 的入参的子集,则 A 比 B 更精确,重载就会选择 A。换成上面这两个就是,char[] 入参的比 object 的更精确,因为 object 包含 char[],所以 String.valueOf(null) 是用 char[] 入参这个重载方法。
看看这个方法的实现:
/**
* Returns the string representation of the <code>char</code> array
* argument. The contents of the character array are copied; subsequent
* modification of the character array does not affect the newly
* created string.
*
* @param data a <code>char</code> array.
* @return a newly allocated string representing the same sequence of
* characters contained in the character array argument.
*/
public static String valueOf(char data[]) {
return new String(data);
}
直接 new String,再看 new String 的实现:
/**
* Allocates a new {@code String} so that it represents the sequence of
* characters currently contained in the character array argument. The
* contents of the character array are copied; subsequent modification of
* the character array does not affect the newly created string.
*
* @param value
* The initial value of the string
*/
public String(char value[]) {
this.offset = 0;
this.count = value.length;
this.value = StringValue.from(value);
}
第12行,入参为 null 就报 NPE 了。
JDK 中的奇葩实现比较多,大家用的时候养成多看源码实现的好习惯,可以避免踩坑...
评论区