日本综合一区二区|亚洲中文天堂综合|日韩欧美自拍一区|男女精品天堂一区|欧美自拍第6页亚洲成人精品一区|亚洲黄色天堂一区二区成人|超碰91偷拍第一页|日韩av夜夜嗨中文字幕|久久蜜综合视频官网|精美人妻一区二区三区

RELATEED CONSULTING
相關(guān)咨詢(xún)
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時(shí)間:8:30-17:00
你可能遇到了下面的問(wèn)題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營(yíng)銷(xiāo)解決方案
String拼接出現(xiàn)Null?你看到的分析可是錯(cuò)的

本文轉(zhuǎn)載自微信公眾號(hào)「程序新視界」,作者二師兄 。轉(zhuǎn)載本文請(qǐng)聯(lián)系程序新視界公眾號(hào)。

前言

String類(lèi)型真是個(gè)神奇的存在,動(dòng)不動(dòng)就會(huì)出現(xiàn)一些迷惑人的錯(cuò)誤。今天看到一篇文中提到當(dāng)String的值為null時(shí),進(jìn)行字符串相加拼接,會(huì)出現(xiàn)把null當(dāng)做字符串拼接的現(xiàn)象。

比如下面這段代碼:

 
 
 
 
  1. String s = null;
  2. s = s + "hello";
  3. System.out.println(s + " world");

你預(yù)期的結(jié)果可能是“hello world”,但實(shí)際的結(jié)果是“nullhello world”,神奇吧。

其實(shí)這倒沒(méi)什么,實(shí)踐一下就可以看到結(jié)果。但當(dāng)你好奇心作祟,在網(wǎng)上搜為什么時(shí),你看到的答案可能是錯(cuò)的。

我在搜索時(shí),看到訪問(wèn)量上萬(wàn)的文章給出的解釋竟然錯(cuò)誤的。為了排除一些誤導(dǎo),特意為大家分析一下原因。

錯(cuò)誤的原因分析

如果對(duì)上述問(wèn)題進(jìn)行搜索,你可能看到的答案是:

 
 
 
 
  1. s + " world" 等價(jià)于 s = String.valueOf(s)+"word";

然后附帶valueOf方法:

 
 
 
 
  1. public static String valueOf(Object obj) {
  2.   return (obj == null) ? "null" : obj.toString();
  3. }

你信了嗎?如果信了可能真的就錯(cuò)了。下面我們就來(lái)分析分析為什么錯(cuò)了。

Java編譯器的優(yōu)化

我們知道,當(dāng)我們寫(xiě)下面的代碼時(shí)Java編譯器會(huì)為我們做一些優(yōu)化:

 
 
 
 
  1. String a = "Hello ";
  2. String b = "World";
  3. System.out.println(a + b);

如何優(yōu)化的?上面這段代碼經(jīng)過(guò)編譯器優(yōu)化之后,等價(jià)于:

 
 
 
 
  1. StringBuilder sb = new StringBuilder();
  2. sb.append("Hello ");
  3. sb.append("World");
  4. String result = sb.toString();
  5. System.out.println(result);

也就是說(shuō),加號(hào)操作會(huì)被優(yōu)化基于StringBuilder的操作,而并不是上面提到的String.valueOf操作。

那么,上面為null的情況也就等價(jià)于下面的操作了:

 
 
 
 
  1. StringBuilder sb = new StringBuilder(null);
  2. sb.append("hello");
  3. sb.append(" world");
  4. String result = sb.toString();
  5. System.out.println(result);

此時(shí),我們?cè)倏匆幌耂tringBuilder(null)這個(gè)構(gòu)造方法的底層實(shí)現(xiàn),最終調(diào)到它的父類(lèi)AbstractStringBuilder中的append方法:

 
 
 
 
  1. public AbstractStringBuilder append(String str) {
  2.     if (str == null)
  3.         return appendNull();
  4.     int len = str.length();
  5.     ensureCapacityInternal(count + len);
  6.     str.getChars(0, len, value, count);
  7.     count += len;
  8.     return this;
  9. }

對(duì)應(yīng)的appendNull方法實(shí)現(xiàn)為:

 
 
 
 
  1. private AbstractStringBuilder appendNull() {
  2.     int c = count;
  3.     ensureCapacityInternal(c + 4);
  4.     final char[] value = this.value;
  5.     value[c++] = 'n';
  6.     value[c++] = 'u';
  7.     value[c++] = 'l';
  8.     value[c++] = 'l';
  9.     count = c;
  10.     return this;
  11. }

在appendNull方法中就是將null當(dāng)做字符串“null”來(lái)處理了。這也就是為什么會(huì)在拼接中出現(xiàn)null的原因。

字節(jié)碼追蹤

針對(duì)上述示例,如果你想看編譯器是如何處理的,可以通過(guò)javap -c 命令來(lái)查看對(duì)應(yīng)字節(jié)碼:

通過(guò)字節(jié)碼可以看出,基本上與上面的分析的一致。所以說(shuō),盡信書(shū)不如無(wú)書(shū)。

拓展問(wèn)題

解決了上述問(wèn)題,再來(lái)看看,如果我們單純的就打印null是怎么輸出的?

 
 
 
 
  1. String s = null;
  2. System.out.println(s);

執(zhí)行上述程序,控制臺(tái)打印null,這個(gè)null是哪兒來(lái)的呢?直接看println的底層實(shí)現(xiàn):

 
 
 
 
  1. public void print(String s) {
  2.     if (s == null) {
  3.         s = "null";
  4.     }
  5.     write(s);
  6. }

最終調(diào)用到了print方法,如果為null,則打印null字符串。

支持,還沒(méi)有出現(xiàn)最初的valueOf方法,那么valueOf方法在什么場(chǎng)景下會(huì)用到呢?在對(duì)象為Object類(lèi)型時(shí):

 
 
 
 
  1. Object s = null;
  2. String s1 = String.valueOf(s);
  3. System.out.println(s1);

也就是說(shuō)在明確調(diào)用valueOf方法時(shí),此時(shí)s1的值直接是null字符串。

再拓展一下,針對(duì)一些基礎(chǔ)類(lèi)型的包裝類(lèi),比如Integer、Double等:

 
 
 
 
  1. Integer i = null;
  2. System.out.println(i);

上述代碼的處理又不太一樣,println方法實(shí)現(xiàn)如下:

 
 
 
 
  1. public void println(Object x) {
  2.     String s = String.valueOf(x);
  3.     synchronized (this) {
  4.         print(s);
  5.         newLine();
  6.     }
  7. }

也就是說(shuō)先對(duì)對(duì)應(yīng)的Object對(duì)象調(diào)用valueOf,回到上面的示例,如果Object為null,該方法返回null字符串,后續(xù)打印機(jī)直接為null。

小結(jié)

字符串拼接是很常見(jiàn)的問(wèn)題,一不小心會(huì)出現(xiàn)將null給拼接上的情況。而這狀況的出現(xiàn)又牽扯到Java編譯器的優(yōu)化,是不是很有意思?而且正如最開(kāi)始所述,當(dāng)我們?cè)诰W(wǎng)絡(luò)上搜索資料時(shí)也要辨證的去看待答案的準(zhǔn)確性。


本文名稱(chēng):String拼接出現(xiàn)Null?你看到的分析可是錯(cuò)的
文章地址:http://www.dlmjj.cn/article/cdhedio.html