equals()與 == 在java編程或系統實際可發中都會用到,但是二者又有實際的區別。千萬不要理所當然地認為equals()與==的作用就是一樣的,下面就一步步來闡述二者的區別。
phone.java
建立phone類,有兩個私人的成員變數price與memory,在構造器中對其進行初始化。
package testPackage;public class phone { private float price;//價格 private int memory;//記憶體 public phone(float price, int memory) { super(); this.price = price; this.memory = memory; }}
testPhone.java
建立兩個手機對象,兩個私人成員變數都賦一樣值,用equals()進行比較
package testPackage;public class testPhone { public static void main(String[] args){ phone p1 = new phone(4000f,16);//4000元,16G記憶體的手機p1 phone p2 = new phone(4000f,16);//4000元,16G記憶體的手機p2 if(p1.equals(p2)){//如果p1等於p2 System.out.println("p1與p2相同"); } else{//p1不等於p2 System.out.println("p1與p2不相同"); } }}
運行結果:
p1與p2不相同
結果分析:
儘管兩個手機對象的私人成員變數全部相同,equals()運行結果顯示這兩個對象是不相同的。這是為什麼呢。
還有,phone類中並沒有定義equals()方法,這個equals()方法哪裡來的。
相信大家都知道java中的所有類都繼承了Object.class,因此,所有類都繼承了Object類中的equals()方法,要想知道運行結果的本質原因必須查看Object.class的源碼。
開啟Object.class的源碼找到定義equals()方法的位置:
public boolean equals(Object obj) { return (this == obj);}
發現Object.class給出equals()方法的定義,竟然只是簡單地通過==去實現判斷。而==在java中用於判斷儲存在棧中的值是否相等。我們的基礎資料型別 (Elementary Data Type)像int的比較都用==,因為基礎資料型別 (Elementary Data Type)就存放在棧中,同樣存放在棧中的,還有引用資料類型的引用,而真正的對象本身則存放在堆中。因此,這裡給出的equals()方法就只是比較兩個對象在記憶體中的引用(即地址)是否相等。本例中建立了兩個對象,在記憶體中就新開闢了兩個記憶體空間,引用地址當然是不一樣的,程式運行結果當然是不相同。
但是我們想通過兩個手機的價格與記憶體相同就判斷手機是相同的,確實實際開發中我們都是這樣想的,那應該怎麼辦呢。重寫equals()方法。
phone.java中重寫equals()方法:
package testPackage;public class phone { private float price;//價格 private int memory;//記憶體 public phone(float price, int memory) { super(); this.price = price; this.memory = memory; } @Override public boolean equals(Object obj){ if(this == obj){//如果引用地址是相同的,證明是同一個對象,那當然相同 return true; } if(obj ==null){//如果對象是空的,沒有比較的必要,直接返回false return false; } if(!(obj instanceof phone)){//如果obj不是phone的一個對象執行個體,直接返回false return false; } phone p = (phone)obj;//編譯需要,強制類型轉換 if( this.price==p.price && this.memory==p.memory ){ return true; } else{ return false; } }}
重新運行testPhone.java,查看運行結果:
運行結果:
p1與p2相同
結果分析:
通過重寫equals()實現了通過私人成員變數判斷兩個手機對象是否相等,若prize與memory都相等,則兩個手機對象就相等。
看到這裡,相信大家對equals()與==的區別都有一定理解了,但是顯然還不夠,關於二者的區別,還有值得瞭解的地方。
建立testString.java進行字串測試
package testPackage;public class testString { public static void main(String[] args){ String s1 = "我是手機1"; String s2 = new String("我是手機1"); System.out.println(s1==s2); System.out.println(s1.equals(s2)); }}
運行結果:
false
true
結果分析:
在java中,字串是引用資料類型,以執行個體對象的形式存在。因此,雖然s1與s2看上去定義方式不同,但是它們都建立了對象,本質其實是一樣的。
如上所說,==比較的是引用資料類型在棧中的地址是否相同,s1與s2都建立了兩個字串對象,當然開闢了兩個不同的記憶體空間,結果返回false當然是意料之中的。
但是s1.equals(s2)為什麼返回true呢。按上面所說Object.class不也是直接通過==進行判斷的嗎。結果應該是false吧。這時不妨大膽開啟String的源碼。
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; }
發現String.class給出了對Object.class中equals()方法的重寫,重寫後equals()要判斷兩個字串的字元是否全部相等。
這是修改一下s2的字元再重新測試:
public static void main(String[] args){ String s1 = "我是手機1"; String s2 = new String("我是手機2"); System.out.println(s1==s2); System.out.println(s1.equals(s2)); }
運行結果:
false
false
結果分析:
由於s1與s2的字元不完全相同,因此equals()方法返回false
到這裡,給出在實際應用中equals()與==的提示: 若是兩個基礎資料型別 (Elementary Data Type)的比較,例如int a = 1,b = 2;比較a是否等於b。使用== 若要通過比較成員變數判斷兩個對象是否相等(對象不是字串),例如自己寫的phone對象,要重寫從Object類繼承來的equals()方法實現。 若是比較兩個字串,直接用equals()方法。