Java中關於Integer, String 類型變量 == 與 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:作者水平有限, 歡迎大佬指點不足.


免責聲明!

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



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