再也不要對java中==和equals的區別有困惑了,這篇文章保證你能懂
想到你應該無數次看到過這個問題了,也可能你已經看過無數篇文章了,如果你還是一頭霧水或者是不理解,那試著看看這篇文章,相信你一定能看懂。
一、理解”==“的含義
在java中,主要有兩個作用。
1、基礎資料型別:比較的是他們的值是否相等,比如兩個int型別的變數,比較的是變數的值是否一樣。
2、引用資料型別:比較的是引用的地址是否相同,比如說新建了兩個User物件,比較的是兩個User的地址是否一樣。
OK。
到這就注意了,你會發現,我在舉引用的例子的時候,使用的是User物件,而不是String
。彆著急接著往下看。
二、理解equals的含義
先看看他的原始碼,equals方法是在Object中就有。
注意了這裡的原始碼是Object裡面的equals。
從這個原始碼中你會發現,比較的是當前物件的引用和obj的引用是否相同,也就是說比較的預設就是地址。還記的在上面我們使用的是User而不是String嘛?在這裡==比較的是引用的地址,equals也是比較的是引用的地址,所以他們的效果在這裡是一樣的。
現在你會發現好像equals的作用和==沒什麼區別呀,那String型別那些亂七八糟的東西是什麼呢?繼續往下看馬上揭曉。
三、重寫equals
1、String中equals方法
看到這個標題相信你已經能找到答案裡,Object物件裡面的==和equals沒有什麼區別,這樣一看equals方法存在的意義真的不大,不過後來String在Object的基礎之上重寫了equals,於是功能被大大的改變了。如何重寫的呢?我們去String的原始碼中找尋答案:
從上面的原始碼,我們能夠獲取到的資訊是:
String中的equals方法其實比較的是字串的內容是否一樣。也就是說如果像String、Date這些重寫equals的類,你可要小心了。使用的時候會和Object的不一樣。
2、測試String
看看下面的程式碼:
在上面的程式碼中,定義了三個字串,分別使用==和equals去比較。為什麼會出現這樣一個結果呢?還需要從記憶體的角度來解釋一下。
3、記憶體解釋
在java中我們一般把物件存放在堆區,把物件的引用放在棧區。因此在上面三個字串的記憶體狀態應該是下面這樣的。
現在明白了吧。
(1)String str1 = “Hello”會在堆區存放一個字串物件
(2)String str2 = new String(“Hello”)會在堆區再次存放一個字串物件
(3)String str3 = str2這時候Str3和Str2是兩個不同的引用,但是指向同一個物件。
根據這張圖再來看上面的比較:
(1)str1 == str2嘛?意思是地址指向的是同一塊地方嗎?很明顯不一樣。
(2)str1 == str3嘛?意思是地址指向的是同一塊地方嗎?很明顯不一樣。
(3)str2 == str3嘛?意思是地址指向的是同一塊地方嗎?很明顯內容一樣,所以為true。
(4)str1。equals(str2)嘛?意思是地址指向的內容一樣嘛?一樣。
(4)str1。equals(str3)嘛?意思是地址指向的內容一樣嘛?一樣。
(4)str2。equals(str3)嘛?意思是地址指向的內容一樣嘛?一樣。
OK。現在不知道你能理解嘛?
4、總結:
(1)、基礎型別比較
使用==比較值是否相等。
(2)、引用型別比較
①重寫了equals方法,比如String。
第一種情況:使用==比較的是String的引用是否指向了同一塊記憶體
第二種情況:使用equals比較的是String的引用的物件內用是否相等。
②沒有重寫equals方法,比如User等自定義類
==和equals比較的都是引用是否指向了同一塊記憶體。
5、一個小問題
當然了,String型別到這還沒結束,有一個小問題需要大家注意一下。比如看下面的程式碼:
在這裡多了一個intern方法。他的意思是檢查字串池裡是否存在,如果存在了那就直接返回為true。因此在這裡首先s1會在字串池裡面有一個,然後 s2。intern()一看池子裡有了,就不再新建了,直接把s2指向它。