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