“==”和equals

一直對Java中的“==”和equals的用法一知半解,在實際使用中又因為Character、String等分裝類且伴隨toString和String.valueOf等方法的使用后則更加傻傻分不清楚,需要不斷調(diào)試才能完全搞定,因此痛定思痛,收集了一串資料終于徹底搞懂后,寫以此文,便于自身回顧,同時以饗讀者。

個人認(rèn)為《淺談Java中的equals和“==”》 這篇文章講的比較好,本文中的一些示例代碼和關(guān)鍵知識點(diǎn)也引用于該文章。

要理解關(guān)系操作符“==”和equals的區(qū)別首先要搞清楚數(shù)據(jù)變量類型,JAVA中存在基本數(shù)據(jù)類型變量和非基本數(shù)據(jù)類型變量(專業(yè)點(diǎn)的叫法是對象的引用變量),Java中有8種基本數(shù)據(jù)類型:

浮點(diǎn)型:float(4 byte), double(8 byte)

整型:byte(1 byte), short(2 byte), int(4 byte) , long(8 byte)

字符型: char(2 byte)

布爾型: boolean

需要指出的是這8種基本數(shù)據(jù)類型的變量直接存放在棧中,變量直接存儲的是“值”本身,而不是“地址”。因此在用關(guān)系操作符“==”來進(jìn)行比較時,比較的就是 “值” (這樣設(shè)計的原因是棧有一個很重要的特性,存取速度比堆要快,存在棧中的數(shù)據(jù)可以共享,說白了就是為了提升性能)。引用類型的變量存儲的并不是對象的 “值”本身,而是于其關(guān)聯(lián)的對象在內(nèi)存中的地址(如圖 1)。

圖1 引用數(shù)據(jù)類型在內(nèi)存中的組織形式

看如下代碼:

public class Test1 {

public static void main(String[] args) {

int n=3;

int m=3;

System.out.println(n==m); //true

String str = new String("abc");

String str1 = new String("abc");

String str2 = new String("abc");

System.out.println(str1==str2); //false

str1 = str;

str2 = str;

System.out.println(str1==str2); // true

}

由于m和n中直接存儲的是值3,因此比較m==n時,等價于比較3==3?顯然是相等的,返回true。而比較引用類型變量str1==str2時,等價于比較對象的地址值0x001==0x333?顯然是不相等的,返回false,口語化的表示方式為str1和str2指向的是兩個不同的對象。而將str引用對象的地址值賦值給變量str1和str2后,str1和str2都指向了堆中同一對象。

我們再來看一段代碼:

public class Test1 {

public static void main(String[] args) {

System.out.println("abc"=="abc"); //true

System.out.println(new String("abc")==new String("abc")); // false

}

看了上面這段代碼,估計很多人不敢相信這樣的結(jié)果,那么就在電腦上自己敲一遍。要理解上述結(jié)果的差異,我們需要知道String是一種特殊的包裝類數(shù)據(jù)類型,它不屬于8種基本數(shù)據(jù)類型,但是我們可以像基本數(shù)據(jù)類型那樣,不通過new的方法在棧中直接創(chuàng)建String類型數(shù)據(jù),且也是共享的,意思是棧中只存在一個“abc”,因此比較的兩個“abc”實際上是同一個。

而通過new()方法創(chuàng)建的兩個String類型對象存放于堆中,雖然在棧中沒有創(chuàng)建String類型的引用變量指向他們,但是還是比較的是兩個對象的地址值。提示:只有通過new()方法才能保證每次都創(chuàng)建一個新的對象。

(二) equals方法

那如何才能判斷兩個引用類型變量所指向?qū)ο蟮膬?nèi)容是否相等呢?這時候該equals上場了。equals方法是基類Object中的方法,因此對于所有的繼承于Object的類都會有該方法。要理解equals方法的作用,看源碼是個比較好的方法。

圖2 Objects的equals方法源碼
由圖2可以看出Objects類的equals方法與關(guān)系操作符“==”其實是等價的。而String、Integer等類都對equals方法進(jìn)行了重寫,用來比較指向的對象所存儲的內(nèi)容是否相等。圖3是String類equals方法的具體實現(xiàn),可見equals的實現(xiàn)也是依靠關(guān)系操作符,只是將對象的內(nèi)容徹底暴露了,繞開了地址值的比較。

圖3 String類的equals方法源碼

另需注意:equals方法不能作用于基本數(shù)據(jù)類型的變量。

(三)總結(jié)

(1)對于==,如果作用于基本數(shù)據(jù)類型的變量,則直接比較其存儲的 “值”是否相等;如果作用于引用類型的變量,則比較的是所指向的對象的地址。

(2)對于equals方法,如果沒有對equals方法進(jìn)行重寫,則比較的是引用類型的變量所指向的對象的地址。諸如String、Date等類對equals方法進(jìn)行了重寫的話,比較的是所指向的對象的內(nèi)容。

(3)對于引用類型的變量,用“==”比較返回true的結(jié)果,那么用equals方法比較也一定返回true。



最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 1. Java基礎(chǔ)部分 基礎(chǔ)部分的順序:基本語法,類相關(guān)的語法,內(nèi)部類的語法,繼承相關(guān)的語法,異常的語法,線程的語...
    子非魚_t_閱讀 34,662評論 18 399
  • 如果你沒有深度分析過的話,那么這可能是一個非常靈異的事件。 靈異事件一: 靈異事件二: 靈異事件三: 靈異事件四:...
    TinyDolphin閱讀 514評論 0 3
  • 引入 == 基本數(shù)據(jù)類型(也稱原始數(shù)據(jù)類型) :byte,short,char,int,long,float,do...
    凱諾婷閱讀 1,307評論 1 7
  • 今天是高考第一天。 比較特別的是我弟在考場。 心大的人什么都不能擊潰。但是我還是有一點(diǎn)小小的擔(dān)心和緊張。只要他認(rèn)認(rèn)...
    正山小種ww閱讀 167評論 0 0
  • 羅胖:報告 話說幾個月前,華興資本的分析師劉佳明為寫一分報告要來我們公司調(diào)研,那我就接待了一下?,F(xiàn)在報告出來了,我...
    朱進(jìn)偉西農(nóng)閱讀 688評論 0 0

友情鏈接更多精彩內(nèi)容