都說JDK的實現詭異多,今兒也算是被我踩到一個坑了。
就來說說關於String.valueOf的這個坑。
1 public class TestString { 2 3 public static void main(String[] args){ 4 5 Object obj = null; 6 System.out.println(String.valueOf(obj)); 7 System.out.println(String.valueOf(null)); 8 } 9 }
這段代碼,第一個輸出“null”,沒錯,不是空對象null也不是空串“”,而是一個字符串!!包含四個字母n-u-l-l的字符串...
好吧,我只能說寫這個邏輯的人估計是想逗我們玩兒...
第二個輸出,咋一看沒差別,但是,第二個輸出,拋空指針異常了。
下面來分析分析原因。
先說第一個:
看第一個的源碼實現:
1 /** 2 * Returns the string representation of the <code>Object</code> argument. 3 * 4 * @param obj an <code>Object</code>. 5 * @return if the argument is <code>null</code>, then a string equal to 6 * <code>"null"</code>; otherwise, the value of 7 * <code>obj.toString()</code> is returned. 8 * @see java.lang.Object#toString() 9 */ 10 public static String valueOf(Object obj) { 11 return (obj == null) ? "null" : obj.toString(); 12 }
源碼很簡單,如果對象為空,就返回字符串的"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[]入參這個重載方法。
看看這個方法的實現:
1 /** 2 * Returns the string representation of the <code>char</code> array 3 * argument. The contents of the character array are copied; subsequent 4 * modification of the character array does not affect the newly 5 * created string. 6 * 7 * @param data a <code>char</code> array. 8 * @return a newly allocated string representing the same sequence of 9 * characters contained in the character array argument. 10 */ 11 public static String valueOf(char data[]) { 12 return new String(data); 13 }
直接new String的,再看new String的實現:
1 /** 2 * Allocates a new {@code String} so that it represents the sequence of 3 * characters currently contained in the character array argument. The 4 * contents of the character array are copied; subsequent modification of 5 * the character array does not affect the newly created string. 6 * 7 * @param value 8 * The initial value of the string 9 */ 10 public String(char value[]) { 11 this.offset = 0; 12 this.count = value.length; 13 this.value = StringValue.from(value); 14 }
第12行,入參為null就報NPE了。
JDK中的奇葩實現比較多,大家用的時候養成多看源碼實現的好習慣,可以避免踩坑...
如果大家還有見到什么奇葩實現,熱烈歡迎留言討論,哈哈。