Java基础之equals和==的区别深入解析
Java基礎之equals和==的區別深入解析
以下是本文目錄大綱
1. equals 和 == 的區別
// object類下的equals public boolean equals(Object obj) {return (this == obj);} //String類下的euqals 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;}- 首先,我們知道 == 既可以比較基本類型也可以比較引用類型。對于基本類型就是比較值,對于引用類型就是比較內存地址。
- 通過equals源碼可以看出,equals是java.lang.Object類里面的方法,如果該方法沒有被重寫過默認也是==,String類的equals方法是被重寫過的,先比length是否相同,相同再比較value是否相同,且String類在日常開發中用的比較多,久而久之,形成了equals是比較值的錯誤觀點
接下來我們再看個代碼加深理解
public class stringTest {public static void main(String[] args) {String s1 = new String("abc");String s2 = new String("abc");System.out.println(s1==s2);System.out.println(s1.equals(s2));System.out.println("======================");Set<String> set = new HashSet<>();set.add(s1);set.add(s2);System.out.println(s1.hashCode()+"\t"+s2.hashCode());System.out.println(set.size());System.out.println("============");Person p1 = new Person("abc");Person p2 = new Person("abc");System.out.println(p1 == p2);System.out.println(p1.equals(p2));Set<Person> set2 = new HashSet<Person>();set2.add(p1);set2.add(p2);System.out.println(p1.hashCode()+"\t"+p2.hashCode());System.out.println(set2.size());}}結果:
false true ====================== 96354 96354 1 ============ false false 1163157884 1956725890 2解釋:
- s1,s2是引用類型且是String類型(即equals方法有重寫)
- s1==s2 比較的是內存地址,所以 false
- s1.equals(s2) 的equals重寫過,先比較length,再比較value,所以true
- 復寫后s1,s2是同一個對象,所以hashCore值相同
- 即能解釋 set.size() = 1
同理可以解釋p1和p2
- p1,p2為引用類型且是Person類型(即equals沒有重寫)
- p1==p2 比較的是內存地址,所以 false
- s1.equals(s2) 的equals沒有重寫過等價于==,所以false
- p1,p2是兩個對象,所以hashCore值不相同
- 即能解釋 set2.size() = 2
畫圖:
畫圖如上,自我理解,有錯誤請指出。
總結
== 既可以比較基本類型也可以比較引用類型。對于基本類型就是比較值,對于引用類型就是比較內存地址
Equals的話,它是屬于java.lang.Object類里面的方法,如果該方法沒有被重寫過默認也是==;我們可以看到String類的equals方法是被重寫過的,而且String類在日常開發中用的比較多,久而久之,形成了equals是比較值的錯誤觀點。
具體要看這有沒有重寫Object的hashCode方法和equals方法來判斷。
2. equals 的重寫
可以看出,重寫equals,重寫就要同時重寫equals()和hashCode()。
當一個類有自己特有的“邏輯相等”概念,當改寫equals()的時候,總是要改寫hashCode(),根據一個類的equals方法(改寫后),兩個截然不同的實例有可能在邏輯上是相等的,但是,根據Object.hashCode方法,它們僅僅是兩個對象。以Person為例,兩個人都叫張三,但不是同一個人(equals),需要看的不是名字,而是身份證號碼(hashCode)
因此,違反了“相等的對象必須具有相等的散列碼”。
結論:復寫equals方法的時候一般都需要同時復寫hashCode方法。
3. 復寫hashCode方法,31這個數字的作用
源碼:
public int hashCode() {int h = hash;if (h == 0 && value.length > 0) {char val[] = value;for (int i = 0; i < value.length; i++) {h = 31 * h + val[i];}hash = h;}return h;}計算機的乘法涉及到移位計算。當一個數乘以2時,就直接拿該數左移一位即可!選擇31原因是因為31是一個素數。(素數:質數又稱素數,在一個大于1的自然數中,除了1和此整數自身外,沒法被其他自然數整除的數)
在存儲數據計算hash地址的時候,我們希望盡量減少有同樣的hash地址,所謂“沖突”。
因為任何數n * 31就可以被JVM優化為 (n << 5) -n,移位和減法的操作效率要比乘法的操作效率高的多,對左移虛擬機里面都有做相關優化,并且31只占用5bits。
總結
以上是生活随笔為你收集整理的Java基础之equals和==的区别深入解析的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 如何在IDEA中使用git
- 下一篇: java美元兑换,(Java实现) 美元