一、理解"=="的含義
在java中,主要有兩個作用:
1、基本數據類型:比較的是他們的值是否相等,比如兩個int類型的變量,比較的是變量的值是否一樣。
其中基本數據類型有8個:byte(8位)、short(16位)、int(32位)、long(64位)、float(32位)、double(64位)、char(16位)、boolean(true和false)。
八大基本數據類型對應着各自的封裝類型,提供了更多的方法,且不進行初始化時,值默認為空(基本數據類型必須初始化)。
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)嗎?意思是地址指向的內容一樣嗎?一樣。
(5)str1.equals(str3)嗎?意思是地址指向的內容一樣嗎?一樣。
(6)str2.equals(str3)嗎?意思是地址指向的內容一樣嗎?一樣。
4、總結:
(1)基本類型比較:
①使用雙等號 == 比較的是值是否相等。
②基本數據類型無equals方法(沒有意義)。
(2)引用類型比較:
①重寫了equals方法,比如String。
第一種情況:使用==比較的是String的引用是否指向了同一塊內存。
第二種情況:使用equals比較的是String的引用的對象內用是否相等。
②沒有重寫equals方法,比如User等自定義類。
==和equals比較的都是引用是否指向了同一塊內存。
5、一個小問題:
當然了,String類型到這還沒結束,有一個小問題需要大家注意一下。比如看下面的代碼:
在這里多了一個intern方法。他的意思是檢查字符串池里是否存在,如果存在了那就直接返回為true。因此在這里首先s1會在字符串池里面有一個,然后 s2.intern()一看池子里有了,就不再新建了,直接把s2指向它。