簡單看一段代碼吧:
650) this.width=650;" src="http://s3.51cto.com/wyfs02/M02/71/1F/wKiom1XGtKTxITK5AACRhBmhr74708.jpg" title="搜狗_2015-08-09_10-02-01.png" alt="wKiom1XGtKTxITK5AACRhBmhr74708.jpg" />
結果是:
true false
對於String而言,equals我們犯不了什麼錯誤,可是==是經常讓我們迷惑的地方!
第一,String在編譯期存在最佳化行為
例如,String s = "a" + "b"; 在編譯產生的CLASS檔案中已經是這樣的了:
String s = "ab";
那麼上面的代碼中,s4會在編譯期就變成"abc"嗎?不會,因為s2是一個變數,只能在運行期間確定,而且並沒有強制限制式他不能變。而s5在編譯期間就已經確定為"abc",因為s3是final的,變不了的!
是這樣嗎?
我們來利用反組譯碼命令javap命令看下:
650) this.width=650;" src="http://s3.51cto.com/wyfs02/M02/71/1F/wKiom1XGufqQOkrsAAMBToUUQkA377.jpg" title="搜狗_2015-08-09_10-24-46.png" alt="wKiom1XGufqQOkrsAAMBToUUQkA377.jpg" />
很多指令,我也不懂,我們只看能看得懂的地方,或者猜一猜~
從0到8,根據注釋String ab,應該是對應於代碼的
650) this.width=650;" src="http://s3.51cto.com/wyfs02/M00/71/1B/wKioL1XGvLPif8HqAAA3xNvyUos267.jpg" title="搜狗_2015-08-09_10-27-51.png" alt="wKioL1XGvLPif8HqAAA3xNvyUos267.jpg" />
從而也驗證了,String存在編譯期合并的事實。
從9到28,發生了new 操作,還有append,這應該對應於:
650) this.width=650;" src="http://s3.51cto.com/wyfs02/M01/71/1F/wKiom1XGuyeDPjpxAAAWR85yXxU835.jpg" title="搜狗_2015-08-09_10-29-49.png" alt="wKiom1XGuyeDPjpxAAAWR85yXxU835.jpg" />
這說明,對於String而言,變數與常量的這種“+”操作,實際上在底層是搞成了一個StringBuilder進行append,最後在來一個toString得到的!
從30到32,根據注釋String abc,應該對應於代碼:
650) this.width=650;" src="http://s3.51cto.com/wyfs02/M00/71/1C/wKioL1XGvhzwTwYqAAARxH8m2Ec650.jpg" title="搜狗_2015-08-09_10-33-57.png" alt="wKioL1XGvhzwTwYqAAARxH8m2Ec650.jpg" />
這也說明了,final變數與常量的這種“+”操作,直接編譯合并!
第二,String存在常量池的概念
在編譯期間就確定的String常量,是存在String pool中的,而且是保證全域唯一的。也就是說上面代碼中,s1/s2指向String Pool中的同一個string。
相信到這裡以後String的==以後不會在迷糊了,呵呵~
|