還傻傻分不清楚equals和==的區別嗎?看完就明白了

codevald發表於2021-02-14

解決一個問題的最好方法就是發現一個問題產生的根源,即發現最本質的東西,再去解決它。

Java語言裡面的equals()方法是交給開發者們自己去覆蓋重寫編寫功能的,即讓開發者去定義當滿足什麼條件時,兩個Object是相等的。

equals方法是由Object提供的,允許子類進行重寫。

equals()的原始程式碼實現如下:

public boolean equals(Object obj) {
    return (this == obj);
}

而有一些部落格說equals()是比較具體的內容是不是相同的,這個說法其實不太準確,以偏概全。這個說法的來源是很多教程都是以String類中的equals()為參照物進行舉例,String類的equals()重寫了Object物件的原始equals方法,只會比較具體的內容。

String類的equals()的具體實現程式碼如下:


public boolean equals(Object anObject) {
    if (this == anObject) {
        return true;
    }
    if (anObject instanceof String) {
        String anotherString = (String)anObject;
        int n = count;
        if (n == anotherString.count) {
            char v1[] = value;
            char v2[] = anotherString.value;
            int i = offset;
            int j = anotherString.offset;
            while (n-- != 0) {
                if (v1[i++] != v2[j++])
                    return false;
            }
            return true;
        }
    }
    return false;
}

而 == 是比較兩個引用在記憶體中指向的是不是同一個物件,也就是在記憶體中的儲存地址是不是一樣的,兩個物件的引用相同時(指向的是同一個物件),則 == 會返回true,否則返回false。

所以 == 是和Object類的原始equals()方法是等價的。

現在很多類都對equals進行了重寫,這裡用常見的String類來編寫個測試Demo

public class TestString {

	public static void main(String[] args) {
  
		String string_1 = "codevald";
		String string_2 = "codevald";
		System.out.println(string_1 == string_2); //結果為true
	
	
		String string_3 = new String("codevald");
		String string_4 = "code" + new String("vald");
		System.out.println(string_3 == string_4); //結果為false
		System.out.println(string_3.equals(string_4)); //結果為true

	
	}


}

可以看到Demo中第一個輸出語句結果為true

String string_1 = "codevald"會現在棧中建立一個對String類的引用變數string_1,然後會去字串常量池中尋找有沒有"codevald",因為是第一次建立沒有,則會將"codevald"存放進字串常量池。

String string_2 = "codevald" 又在棧中建立了String類的引用變數string_2,然後會去字串常量池中尋找有沒有"codevald",如果沒有,則會建立並存放進常量池,並將string_2指向"codevald",如果已經有了,則直接令string_2指向"codevald"。上面的程式碼已經將字串儲存進了常量池,所以兩個引用(string_1和string_2)指向同一個"codevald",返回true。

String string_3 = new String("codevald")會在堆中建立一個物件,並將在棧中存在的物件引用指向堆中的物件,而String string_4則是分別用了常量池中的字串和存放物件的堆中的字串,做 + 的時候會進行動態呼叫,最後建立完生成的物件仍然存放在堆中,而兩個物件在堆中的地址是不一樣的,所以 == 會返回false。

而String類重寫了equals方法,比較的是記憶體中存放的資料的具體內容是不是相同的,這裡存放的都是"codevald",所以會返回true。

總結

對於字串變數來說,使用""和"equals"比較字串時,其比較方法不同。""比較兩個變數本身的值,即兩個物件在記憶體中的首地址,"equals"比較字串包含內容是否相同。

對於非字串變數來說,如果沒有對equals()進行重寫的話,"==" 和 "equals"方法的作用是相同的,都是用來比較物件在堆記憶體中的首地址,即用來比較兩個引用變數是否指向同一個物件。

相關文章