== 與 equals()的聯繫: ==: 我們都知道Java中 == 對用於基礎數據類型(byte, short, int, long, float, double, boolean, char)判斷時, 是直接對變數值的比較. 而對於引用類型變數則是對變數地址的比較. equals(): 我們可 ...
== 與 equals()的聯繫:
==:
我們都知道Java中 == 對用於基礎數據類型(byte, short, int, long, float, double, boolean, char)判斷時, 是直接對變數值的比較. 而對於引用類型變數則是對變數地址的比較.
equals():
我們可以通過查閱源碼看到Object類中equals()方法依然是直接對地址的比較
當然, 常見的Java類都重寫了equals方法, 如封裝類, Date等. 這裡我們只說下Integer和String重寫後的equals().
Integer的equals()是利用自動拆箱為int類型數據, 然後進行int值的比較:
而String則是逐個字元的進行比較:
上面所說的也許都知道, 之所以說一遍, 一是為了有些知道但不是很明白的同學. 二是自己再重新總結一次.
然後真正對於Integer 和 String變數 做比較時, 其實還有兩個大坑
不多廢話, 先上測試代碼
看到運行結果是不是蒙了.
按照上面說的, 引用類型變數進行 == 比較時, 比較的是地址, 這樣的話 i1 == i2結果為false我們可以理解. 但是i3 == i4 結果為true似乎解釋不通.
實際上,對於-128 - 127之間的值, Integer對象從IntegerCache.cache中產生, 此範圍內相同值的變數復用cache中對象, 所以指向的地址是相同的.因此i3 == i4 結果為true.
是不是更加懵逼了.
原理與Integer類似, 每個不同值的String類型變數其實是一個"常量". 單獨的存儲在一個特殊區域, 稱為字元串常量池.
每個值不同的String變數在字元串常量池中都是唯一存在的.
舉個慄子說明:
1 String s1 = "1"; 2 String s2 = "1"; 3 String s3 = "12"; 4 System.out.println(s1 == s2);//true 5 System.out.println(s2 == s3);//false
只是如此簡單嗎? 顯然不可能.
來一個測試題: 可以自己思考下再看分析
1 String s1 = "123"; 2 String s2 = "456"; 3 String s3 = "123456"; 4 String s4 = s1 + s2; 5 System.out.println(s3 == s4); 6 System.out.println(s3.equals(s4));
結果順序是:false, true.
是不是又有疑惑了,剛剛還說String變數值相同時, 指向常量池中同一個地址.怎麼就false了呢?
其實對於第4行代碼, 其原理是下麵這樣的
可以看到, 原理是先創建了一個StringBuilder對象,這個對象不是存在於字元串常量池中的哦! 然後分別將s1和s2拼接, 最後s4指向這個對象地址.
這樣如果要進行大量的字元串拼接的話, 會創建很多對象, 造成資源浪費, 所以涉及到大量字元串拼接時建議使用StringBuffer(線程安全)或StringBuilder(非線程安全)來操作.
如果已經暈頭轉向了的話, 不防看下總結.
總結:
1. 對於引用類型變數(尤其是上面說到的兩個), 做比較時, 推薦使用equals.
2. 字元串拼接時, 使用StringBuilder或StringBuffer來代替String.
3. 不要忽略基礎的重要性, 無論學到什麼時候, 基礎都很重要.
4. 關註, 收藏.
PS:作者水平有限, 歡迎大佬指點不足.