Equals和 還分不清?

2021-10-13 07:25:12 字數 4213 閱讀 2003

對於基本型別和引用型別 == 的作用效果是不同的,兩者比較如下

我們可以來看乙個簡單的例項

public static void main(string args)
system.out.println(x==y);對於引用物件的x和y,指向的是同乙個字串,兩個引用是相同的,因此輸出true。

system.out.println(x==z);對於字串z會指向新new出來的乙個字串物件,x與z指向的不是同乙個字串物件。

equals 本質上就是 ==,只不過 string 和 integer 等重寫了 equals 方法,把它變成了值比較。看下面的**就明白了,如果沒有重寫equals方法,預設是按照==進行比較,如果是普通的物件,則比較的是引用型別。

public class equalsandsame 

}class person

public string getname()

public void setname(string name)

public integer getage()

public void setage(integer age)

}

1. object類中的equals()

equals()如果不被重寫,則底層比較方式和==基本一致,底層就是通過==來比較的。

public boolean equals(object obj)
2. 基本型別的equals比較

/**

* 本質上比較integer物件的值

* @param obj 比較的物件

* @return

*/public boolean equals(object obj)

return false;

}

3. string的equals()方法

/**

* 比較兩個字串是否相等

* 當anobject物件不為空且該物件與比較物件完全相等時返回true

* @param anobject

* @return

*/public boolean equals(object anobject)

// 判斷字元是否是字串型別

/*** 2.1 首先判斷兩個字串長度是否相等,相等則繼續比較內部元素;否則直接返回false

* 2.2 利用while迴圈依次比較兩個陣列內部字元是否相等

*/if (anobject instanceof string)

return true;}}

return false;

}

修煉到這種功程度,下次面對這種面試題目,可以這麼說:

==對於不同型別比較的是不同的,基礎型別對比的是值是否相同,引用型別對比的是引用是否相同;而 equals 對於不同的型別比較的是不同的,對於基礎型別因此基礎類本身實現了equals()方法,其底層比較的是值是否相同,對於string比較的是字串內容是否完全相同,而對於其他的型別,如果本身沒有重寫equals()方法,其比較的是引用是否相同,如果實現了equals()方法,則按照實現方法的邏輯進行比較。

上面說到了重寫equals()方法必須重寫hashcode()方法,只是說到了面試中應該怎麼回答,如果對於上面回答不是很理解,下面將深入的講解一番。

hashcode()方法

本身是乙個本地方法,也就是說本身是在本地層面進行求解hashcode()的值的,返回值時int。

public native int hashcode();
原始碼中對於hashcode()也有一些約束,原始碼備註中的翻譯如下:

如果物件在使用equals方法中進行比較的引數沒有修改,那麼多次呼叫乙個物件的hashcode()方法返回的雜湊值應該是相同的

如果兩個物件通過equals方法比較是相等的,那麼要求這兩個物件的hashcode方法返回的值也應該是相等的

如果兩個物件通過equals方法比較是不同的,那麼也不要求這兩個物件的hashcode方法返回的值是不相同的。(換句話說兩個物件equals()不相同,這兩個物件的hashcode()方法可等可不等)但是我們應該知道對於不同物件產生不同的雜湊值對於雜湊表(hashmap)能夠提高效能。

hashcode()的原始碼中一直介紹hashmap,那我們可以看看hashmap中對於hashcode()的應用,先看一下hashmap的基本結構(關於hashmap的知識網上有很多知識,此處不再贅述)

那麼是如何確定乙個資料儲存在陣列中的哪個位置呢?就是通過hashcode方法進行計算出儲存在哪個位置,上面hashcode()規則時說了有可能兩個不同物件的hashcode方法返回的值相同,那麼此時就會產生衝突,產生衝突的話就會呼叫equals方法進行比對,如果不同,那麼就將其加入鍊錶,如果相同就替換原資料。

本身hashmap容器重寫了hashcode()方法的,但是本質上也是呼叫object的hashcode()方法

如果自定義物件作為key但是不重寫hashcode()方法會怎麼樣呢?

先看一下沒有重寫hashcode()的物件

person定義如下:

class person

public string getname()

public void setname(string name)

public integer getage()

public void setage(integer age)

}public class equalsandsame

}

輸出結果出人意料確實null,沒有按照預獲取到2222,為啥會這樣呢?

hashmap是採用hashcode()用來計算該物件放入陣列中的哪個位置,兩個都是重寫new的物件,但是由於沒有重寫,預設都是採用objecthashcode(),雖然裡面的內容都相同,但是物件所處的位址卻不同,所以使用預設的hashcode也就不同,get()方法就以為是獲取另乙個key值。返回的自然是null

如何解決這個問題呢?

可以重寫equals()方法和hashcode()方法,可以通過idea快捷鍵自動生成equals()hashcode()方法

class person

/*** 重寫的hashcode()方法是通過物件的全部欄位來計算hashcode值

* 最底層是通過arrays的hashcode()來計算

* @return

*/@override

public int hashcode()

}

objects.hash()底層是通過arrays.hashcode()實現的

public static int hashcode(object a)
重寫了之後,兩個物件只要各個欄位的值相同,物件的hashcode值必定相同,這也就是為什麼重寫equals()方法的時候要求必須重寫hashcode()方法了

AI新人必看 引數和超引數還分不清楚嗎?

ai新人必看 引數和超引數還分不清楚嗎?計算機學科裡有太多的術語,而且許多術語的使用並不一致。哪怕是相同的術語,不同學科的人理解一定有所不同。比如說 模型引數 model parameter 和 模型超引數 model hyperparameter 對於初學者來說,這些沒有明確定義的術語肯定很令人困...

Scala 傻傻分不清的方法和函式

感性的認識一下方法和函式 方法m 是乙個邏輯操作快 函式f 是物件,可以賦值給乙個變數或常量 函式f 有乙個 轉換符號 object methodandfunctiondemo 定義乙個函式f1,引數是兩個int型別,返回值是乙個int型別 val f1 x int,y int x y 再定義乙個函...

氣泡排序和插入排序傻傻分不清

氣泡排序和插入排序的時間複雜度相同,容易搞混淆。氣泡排序最壞情況時間複雜度o n 2 最好情況時間複雜度o n 插入排序最壞情況時間複雜度也是o n 2 最好情況時間複雜度也是o n 氣泡排序和插入排序都是穩定的,穩定是指如果兩個數相等,排序過後它們的前後順序不變。如a b,排序前a在b的前面,排序...