說說JDK中的String.valueOf()傳null的詭異處理


都說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中的奇葩實現比較多,大家用的時候養成多看源碼實現的好習慣,可以避免踩坑...

如果大家還有見到什么奇葩實現,熱烈歡迎留言討論,哈哈。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM