==和equals有什麼區別?徹底搞懂

java程序中測試兩個變量是否相等有兩種方式,一種是利用==運算符,一種是利用equals()方法。

(1)“==”

==是判斷的意思,對於局部變量的基本類型(byte,short,int,long,float,double,char,boolean)存儲在棧之中,比較的是值,只要值相等,就返回True

 int i=0;
 double x=0.00;
 System.out.println(i==x); // true

而對於引用類型來說,它比較的是變量(棧)內存中存放的對象的(堆)內存地址,用來判斷兩個對象的地址是否相同,即是否是指相同一個對象。

	String i=new String("x");
	String n=new String("x");

	System.out.println(i==n); // false

在舉個例子,對於在常量池的變量來說,又有新情況

		String s3="hello";
        String s4="hello";
   
        System.out.println(s3==s4); // true

這是因爲hello已經在常量池中了,s4只是重新指向了它,並沒有新建一個對象,所以也就沒有對象地址不同的情況了

(2)“equals”

其用於比較對象的地址,所以其對引用類型的比較和==的作用相同

源碼

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

分析:從源碼可以看出,一般情況下,equals和==是等價的

一般引用的equals

對於Integer、Boolean等封裝類來說,重寫了equals

源碼如下
注: instaninstanceof是指,前面的對象是否是後面類的引用

 public boolean equals(Object obj) {
        if (obj instanceof Integer) {
            return value == ((Integer)obj).intValue();
        }
        return false;
    }
 public boolean equals(Object obj) {
        if (obj instanceof Boolean) {
            return value == ((Boolean)obj).booleanValue();
        }
        return false;
    }

分析:雖然增加了一個判斷,但實質上仍然是==的比較

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

分析:這個代碼的意思是,如果兩個對象==成立,那麼就返回true,如果對象中有String,那麼就會一個字符一個字符的比較,判斷字符串中每個字符是否相同。

equals擴展

對於equals,jdk給出了一些解釋

equals方法在非空對象引用上實現等價關係:

  • 自反性 :對於任何非空的參考值x , x.equals(x)應該返回true 。
  • 它是對稱的 :對於任何非空引用值x和y , x.equals(y)應該返回true當且僅當y.equals(x)回報true 。
  • 傳遞性 :對於任何非空引用值x , y和z ,如果x.equals(y)回報true個y.equals(z)回報true ,然後x.equals(z)應該返回true 。
  • 它是一致的 :對於任何非空引用值x和y ,多次調用x.equals(y)始終返回true或始終返回false ,沒有設置中使用的信息equals比較上的對象被修改。
  • 對於任何非空的參考值x , x.equals(null)應該返回false 。

還有需要注意的:
該equals類方法Object實現對象上差別可能性最大的相等關係; 也就是說,對於任何非空的參考值x和y ,當且僅當x和y引用相同的對象( x == y具有值true )時,該方法返回true 。

請注意,無論何時覆蓋該方法,通常需要覆蓋hashCode方法,以便維護hashCode方法的通用合同,該方法規定相等的對象必須具有相等的哈希碼。

equals和hashcode

equals相等就一定有一樣的hashcode,hashcode一樣,equals不一定返回true

簡單解釋hashcode

在這裏插入圖片描述
對於JVM虛擬機來說,在堆中有很多很多的對象,那麼如何去尋找他們,難道從頭遍歷嗎?JVM選擇使用一張表來記錄各個對象的位置,一般由哈希編碼來記錄,每個哈希編碼是獨一無二的,可以根據哈希編碼找到對象地址(也有極少數特殊情況暫不贅述)
hashcode方法在object中定義

public native int hashCode();

native 關鍵字也就說明了這個方法的底層不由Java來實現,該方法會返回object的整型數字

hashcode能大大降低對象比較次數,提高查找效率!

解釋: equals相等就一定有一樣的hashcode,hashcode一樣,equals不一定返回true

如果兩個Java對象A和B,A和B相等(eqauls結果爲true),但A和B的哈希碼不同,則A和B存入HashMap時的哈希碼計算得到的HashMap內部數組位置索引可能不同,那麼A和B很有可能允許同時存入HashMap,顯然相等/相同的元素是不允許同時存入HashMap,HashMap不允許存放重複元素。

假如兩個Java對象A和B,A和B不相等(eqauls結果爲false),但A和B的哈希碼相等,將A和B都存入HashMap時會發生哈希衝突,也就是A和B存放在HashMap內部數組的位置索引相同這時HashMap會在該位置建立一個鏈接表,將A和B串起來放在該位置,顯然,該情況不違反HashMap的使用原則,是允許的。
舉個例子

1 String str1 = "通話";
2 String str2 = "重地";
3 System.out.println(String.format("str1:%d | str2:%d",  str1.hashCode(),str2.hashCode()));
4 System.out.println(str1.equals(str2));
執行的結果:

str1:1179395 | str2:1179395

false

很顯然“通話”和“重地”的 hashCode() 相同,然而 equals() 則爲 false,因爲在散列表中,hashCode()相等即兩個鍵值對的哈希值相等,然而哈希值相等,並不一定能得出鍵值對相等。

參考博客:https://www.cnblogs.com/Qian123/p/5703507.html#_label1

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章