equals()方法详解
Java語言中equals()方法的使用可以說比較的頻繁,但是如果輕視equals()方法,一些意想不到的錯誤就會產生。哈哈,說的有點嚴重了~
先談談equals()方法的出身。equals()方法在java.lang.Object類中聲明,由于Object類是Java所有類的基類,因此equals()方法在Java中無所不在,我也是驚呆了。先貼一
段java.lang.Object類的英文說明:
Class Object is the root of the class hierarchy. Every class has Object as a superclass. All objects,?including arrays, implement the methods of this class.
翻譯一下:Object類是類繼承樹中的根類。每個類都把Object類作為其超類。所有的對象,包括數組,都實現了Object類所有的方法。
java.lang.Object類中的equals()方法如何聲明的呢?源代碼是這么寫的:
1 public boolean equals(Object obj) { 2 return (this == obj); 3 }稍微解釋一下,這段代碼就是說如果有 obj1.equals(obj2),那么返回值就是判斷obj1和obj2堆地址是否相同(也就是說是否是同一塊內存,即是否是同一個對象)。
階段性總結一下java.lang.Object類的equals()方法:
1) equals()方法使用必須要有2個對象;
2) equals()方法返回的是一個boolean值,如果是同一個對象則返回true,否則返回false;
3) equals()方法本質還是使用了"=="雙目運算符。("==":基本數據類型比較內容是否相同;引用數據類型比較對象hashCode是否相同,即引用指向的對象是否是同一個)。
摘自java.lang.Object類的equals()方法說明:equal objects must have equal hash codes
解釋完Object類的equals()方法后,我試著用例題的形式來分析一下這些繼承Object類的派生類equals()方法。一般來說Java核心類庫中的類幾乎都有equals()的重寫,但是
自己寫的類就沒有重寫咯。如果你沒區別這兩者就貿然使用equals()方法,那很可能還是在使用Object類的equals()方法。
類型一: Object類的派生類沒有重寫Object類的equals()方法
1 class MyClass{ 2 int x; 3 4 MyClass(int i){ 5 x=i; 6 } 7 8 public static void main(String[] args){ 9 MyClass m1=new MyClass(100); 10 MyClass m2=new MyClass(100); 11 if(m1.equals(m2)){ 12 System.out.println("Both are equal");} 13 else{ 14 System.out.println("Both are not equal"); 15 } 16 } 17 }?A代碼編譯時報出錯誤提示信息"equals()方法未定義"
?B.編譯通過,拋出運行期異常.
?C.輸出Both are equal.
?D.輸出Both are not equal
分析:做錯這道題的原因很多,但是做對這題的原因只有一個,那就是真正理解了equals()方法的前因后果。本題中MyClass類隱繼承了Object類(所有類的基類),但是并沒
有重寫Object類中的equals()方法。因此情況就是MyClass類和Object類的equals()方法是同一個,只不過MyClass類調用Object類的equals()方法而已。
1 public class MethodOverrideVsOverload { 2 public boolean equals( MethodOverrideVsOverload other ) { 3 System.out.println("MethodOverrideVsOverload equals method reached" ); 4 return true; 5 } 6 7 public static void main(String[] args) { 8 Object o1 = new MethodOverrideVsOverload(); 9 Object o2 = new MethodOverrideVsOverload(); 10 11 MethodOverrideVsOverload o3 = new MethodOverrideVsOverload(); 12 MethodOverrideVsOverload o4 = new MethodOverrideVsOverload(); 13 14 if(o1.equals(o2)){ 15 System.out.println("objects o1 and o2 are equal"); 16 } 17 18 if(o3.equals(o4)){ 19 System.out.println("objects o3 and o4 are equal"); 20 } 21 } 22 } 23 輸出結果為:MethodOverrideVsOverload equals method reached
objects o3 and o4 are equal
? 分析:這道題不僅考察了"重寫",也考察了"向上造型"現象。如果這道題做錯,我感覺很可能是你認為下面這段代碼是重寫了java.lang.Object類的equals()方法。
1 public boolean equals( MethodOverrideVsOverload other ) { 2 System.out.println("MethodOverrideVsOverload equals method reached" ); 3 return true; 4 }其實不然,java.lang.Object類equals()方法的簽名和這個方法的簽名是不一樣的,不一樣在哪?一看就知道是參數列表嘛,兩個字母差這么多呢~。所以啊,Object o1,o2
指向子類對象的情況并不是方法重寫,只是發生了方法重載,o1和o2仍然會調用java.lang.Object類的equals()方法。不明白的建議溫故一下方法重載(overload)&重寫
(override)這兩者。關于Java"向上造型"語法現象具體機制我會專門寫一篇總結來解釋的。
?
類型二:Object類的派生類重寫了Object類的equals()方法?
其實在Java Core Class Library中幾乎都重寫了java.lang.Object類的equals()方法。下面僅僅舉2個常見的重寫equals()方法的類。
(1) String類重寫Object類的equals()方法
1 public boolean equals(Object anObject) { 2 if (this == anObject) { 3 return true; 4 } 5 if (anObject instanceof String) { 6 String anotherString = (String)anObject; 7 int n = count; 8 if (n == anotherString.count) { 9 char v1[] = value; 10 char v2[] = anotherString.value; 11 int i = offset; 12 int j = anotherString.offset; 13 while (n-- != 0) { 14 if (v1[i++] != v2[j++]) 15 return false; 16 } 17 return true; 18 } 19 } 20 return false; 21 }? 下面分析一下String類equals()方法的源代碼:
1 if (this == anObject) { 2 return true; 3 } // 這段其實就是Object類的翻版,功能一模一樣主要用于String類在constant pools(方法區常量池)的判斷,如果是同一個對象那么就不用再判斷兩個對象是否內容相同了。寫在開頭是必須的,你說勒!
1 if (anObject instanceof String) { 2 String anotherString = (String)anObject; 3 int n = count; 4 if (n == anotherString.count) { 5 char v1[] = value; 6 char v2[] = anotherString.value; 7 int i = offset; 8 int j = anotherString.offset; 9 while (n-- != 0) { 10 if (v1[i++] != v2[j++]) 11 return false; // 一有內容不同就返回false 12 } 13 return true; // 字符串內容均相同則返回true 14 } 15 }如果傳入的是String類的對象,那么就是兩個對象的內容比較,如果一有內容不同就返回false,均相同則返回true。
(2) Arrays類重寫Object類的equals()方法
Arrays類的equals()方法有些區別,就是只加了static修飾符,當然這仍然是方法重寫(只要派生類訪問權限大于等于超類,派生類返回值類型是超類的子類,并且方法簽名相
同,那么就可以方法重寫)。而且Array類的equals()方法還重載了蠻多的,下面就舉其中的long型(第一個)的例子加以說明:
public static boolean equals(long[] a, long[] a2) {if (a==a2)return true; // 如果數組引用指向同一個數組對象,那么顯然是相同,返回trueif (a==null || a2==null)return false; // 兩個比較的數組不能是nullint length = a.length;if (a2.length != length)return false; // 如果兩個數組不等長,顯然也不可能相等for (int i=0; i<length; i++)if (a[i] != a2[i])return false; // 如果兩個數組等長,那么比較數組的元素,如果所有元素相同,那么這兩個數組相同,反之不同return true; }?
總結:
1) 對于equals()方法,無論如何都不能太輕視。在equals()內部其實也是有"=="在實現部分功能的。
2) 對于基本數據類型,"=="比較的變量的內容是否相同;對于引用數據類型,"=="比較的是對象的地址是否相同。
3) String類的equals()方法比較的是字符串是否內容相同。很多人誤用,我猜可能就是這家伙惹的禍吧,嘻嘻~。
轉載于:https://www.cnblogs.com/forget406/p/5047020.html
總結
以上是生活随笔為你收集整理的equals()方法详解的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: python模块介绍-locustio:
- 下一篇: 发布程序后显示:未能创建类型