Java中的Object類 (上篇)
要麼讀書,要麼旅行,身體和心靈總有一個要在路上。——羅馬假日
咱今天學習的是Java的Object類,首先先看程式碼,類裡面有哪些方法。
咱今天學習兩個方法,分別是hashCode,equals。
Object中的hashCode方法就是根據一定的規則與物件相關的資訊對映成一個數值,這個數值稱為雜湊值。
public native int hashCode();
這時有個關鍵字native,Java平臺有個使用者和本地C程式碼進行互動操作的API,稱為Java Native Interface(簡稱為JNI)。
Object中的equals方法是用來比較兩個物件是否相等的,即object1.equals(object2)為true,則表示object1和object2實際上是引用的同一個物件,但是我們大部分時候進行的是兩個物件值的比較,而非地址的比較,所以這個時候,Object的equals方法就不行了。
這時候有的小哥哥要說不對啊,我們平常也使用了String,Integer,Long型別也進行了equals比較啊,他是比較的值,而非地址,你這不會瞎扯淡吧。
不慌不慌,咱慢慢看,先上程式碼看一下,如果是String型別,使用equals是不是比較的值。
public class Test { public static void main(String[] args){ String str1="abc"; String str2="abc"; System.out.println(str1.equals(str2)); } }
咱執行下程式碼,會發現的確列印的true,說明是比較了str1和str2的值。因為在上篇我們說過了str是一個常量,每次的string型別的資料的地址都是不一樣的,不明白的可以移步上篇,https://blog.csdn.net/qq_33774822/article/details/82757055,那不打臉了嗎。
開玩笑,怎麼可能打臉呢,那咱來看一下這個為什麼呢
原來啊,是String類裡面重寫了equals方法,980行到994行之間就是對兩個string型別資料的比較。感謝Java粑粑,這時候是不是應該響起一首歌,你還要我怎樣,要怎樣。
但是這是常見的型別,那比如我們自定義了一個物件型別,要比較兩個物件是否相等,那該怎麼做呢,應該是重寫equals方法,這裡說明一下,如果兩個物件通過equals來比較返回的是true,就說明這兩個值相等,那麼這兩個物件的hashCode也應該返回相同的值。這是hashCode的常規規定,咱必須得遵守呢。
hashCode還有一個規定就是在程式執行時,同一物件多次呼叫hashCode方法應該返回相同的值。
基於以上的兩個規定,我們自定義了一個Person類,裡面有id,name,還重寫了equals和hashCode方法。
上程式碼咯:
public class Person {
private String id;
private String name;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public boolean equals(Object o) {
if (o == this) {
return true;
}
if (!(o instanceof Person)) {
return false;
}
Person person = (Person) o;
return person.getId().equals(id) && person.getName().equals(name);
}
@Override
public int hashCode() {
int result = 17;
result = result * 31 + name.hashCode() + id.hashCode();
return result;
}
}
這裡要重點說明一下重寫hashCode的時候,用的是31來乘以result,這是為了讓產生的hashCode唯一。
主要的原因有兩個:
1.更少的乘積結果衝突。31是質數中不大不小的存在,如果使用如3這樣比較小的質數,那麼得出的乘積會在一個很小的範圍內,很容易造成雜湊值衝突。如果選擇100以上的質數,得到的雜湊值會超過int的最大範圍。所以這兩種都不適合。
2.31可以被JVM優化,31=2<<5-1,JVM可以自動識別為位運算。