對於基本型別和引用型別 == 的作用效果是不同的,兩者比較如下
我們可以來看乙個簡單的例項
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的物件,但是由於沒有重寫,預設都是採用object
的hashcode()
,雖然裡面的內容都相同,但是物件所處的位址卻不同,所以使用預設的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的前面,排序...