程式扎記: [ Java 小學堂 ] Java 世界裡 equals 與 == 的差別

標籤

2010年7月31日 星期六

[ Java 小學堂 ] Java 世界裡 equals 與 == 的差別


轉載自 這裡
前言 :
在Java裡,equals和==常令程式設計師困惑,這裡簡單說明如下 :
1. ==
測試物件參考時,唯有當兩個參考指向同一物件時,==運算子的結果才為true,同樣的,唯有當兩個參考指向不同物件時,!=運算子的結果才為true,這兩個運算子的處理與物件的內容無關。需要特別注意的是,在String中使用==,因為Java為節省記憶體,會在某一輪調區中維護唯一的String物件,所以如果在類別裡使用同一字串,Java只會建立一個唯一的字串而已。

2. equals
另一種測試的做法是equals,equals在類別為Java原先就存在時,是比較兩個物件是否為相同類型的類別後再比較其內容值是否相同,是就傳回true,否就傳回false。當要測試的類別是自定類別時,要依自定類別所提供的equals來決定如何比較,如果自定類別沒有覆蓋Object的equals類別的話,就以Object的equals來比較,Object的equals的比較方式如同==。

範例程式 :
下面以簡單的範例程式說明 equals 與 == 的差別 :
- myObject1.java 代碼 :
  1. package test;  
  2.   
  3. public class myObject1 {  
  4.      int nNum = 100;  
  5.        
  6.       public void setNum(int nN) {  
  7.         nNum = nN;  
  8.       }  
  9.        
  10.       public int getNum() {  
  11.         return nNum;  
  12.       }  
  13.        
  14.       public void printNum() {  
  15.         System.out.println(nNum);  
  16.       }  
  17. }  
- myObject2.java 代碼 :
  1. package test;  
  2.   
  3. public class myObject2 {  
  4.      int nNum = 100;  
  5.        
  6.       public void setNum(int nN) {  
  7.         nNum = nN;  
  8.       }  
  9.        
  10.       public int getNum() {  
  11.         return nNum;  
  12.       }  
  13.        
  14.       public void printNum() {  
  15.         System.out.println(nNum);  
  16.       }  
  17.        
  18.       public boolean equals(Object obj) {  
  19.         if (obj == nullreturn false;  
  20.         if (!(obj instanceof myObject2)) return false;  
  21.         return this.nNum == ((myObject2) obj).getNum();  
  22.       }  
  23. }  
- myEquals.java 代碼 :
  1. package test;  
  2.   
  3. public class myEquals {  
  4.   
  5.     public myEquals() {  
  6.         //字串型別  
  7.         String sA = "ABC";  
  8.         String sB = "ABC";  
  9.         String sC = new String("ABC");  
  10.        
  11.           //==的比較  
  12.         if (sA == sB)  
  13.           System.out.println("sA == sB (Because of String pool)");  
  14.         else  
  15.           System.out.println("sA != sB");  
  16.        
  17.         if (sA == sC)  
  18.           System.out.println("sA == sC");  
  19.         else  
  20.           System.out.println("sA != sC (Because sC uses new operator)");  
  21.        
  22.           //equals的比較  
  23.         if (sA.equals(sB))  
  24.           System.out.println("sA.equals(sB) = true (Because of the same value)");  
  25.         else  
  26.           System.out.println("sA.equals(sB) = false");  
  27.        
  28.         if (sA.equals(sC))  
  29.           System.out.println("sA.equals(sC) = true (Because of the same value)");  
  30.         else  
  31.           System.out.println("sA.equals(sC) = false");  
  32.        
  33.         //Java原有的型別  
  34.         Long lngA = new Long(100);  
  35.         Long lngB = new Long(100);  
  36.         Long lngC = new Long("100");  
  37.        
  38.           //==的比較  
  39.         if (lngA == lngB)  
  40.           System.out.println("lngA == lngB");  
  41.         else  
  42.           System.out.println("lngA != lngB (Because of the new operator)");  
  43.        
  44.         if (lngA == lngC)  
  45.           System.out.println("lngA == lngC");  
  46.         else  
  47.           System.out.println("lngA != lngC (Because of the new operator)");  
  48.        
  49.           //equals的比較  
  50.         if (lngA.equals(lngB))  
  51.           System.out.println("lngA.equals(lngB) = true (Same value)");  
  52.         else  
  53.           System.out.println("lngA.equals(lngB) = false");  
  54.        
  55.         if (lngA.equals(lngC))  
  56.           System.out.println("lngA.equals(lngC) = true (Same value)");  
  57.         else  
  58.           System.out.println("lngA.equals(lngC) = false");  
  59.        
  60.         //自定型別  
  61.         myObject1 m1A = new myObject1();  
  62.         myObject1 m1B = new myObject1();  
  63.         myObject2 m2A = new myObject2();  
  64.         myObject2 m2B = new myObject2();  
  65.        
  66.           //==的比較  
  67.         if (m1A == m1B)  
  68.           System.out.println("m1A == m1B");  
  69.         else  
  70.           System.out.println("m1A != m1B (Not same memory address)");  
  71.        
  72.         if (m2A == m2B)  
  73.           System.out.println("m2A == m2B");  
  74.         else  
  75.           System.out.println("m2A != m2B (Not same memory address)");  
  76.        
  77.           //equals的比較  
  78.         if (m1A.equals(m1B))  
  79.           System.out.println("m1A.equals(m1B) = true");  
  80.         else  
  81.           System.out.println("m1A.equals(m1B) = false (Not overwtire equals method)");  
  82.        
  83.         if (m2A.equals(m2B))  
  84.           System.out.println("m2A.equals(m2B) = true (Rewrite equals method)");  
  85.         else  
  86.           System.out.println("m2A.equals(m2B) = false");  
  87.       }  
  88.       public static void main(String[] args) {  
  89.         myEquals myEquals1 = new myEquals();  
  90.       }  
  91.   
  92. }  

執行結果 :
sA == sB (Because of String pool)
sA != sC (Because sC uses new operator)
sA.equals(sB) = true (Because of the same value)
sA.equals(sC) = true (Because of the same value)
lngA != lngB (Because of the new operator)
lngA != lngC (Because of the new operator)
lngA.equals(lngB) = true (Same value)
lngA.equals(lngC) = true (Same value)
m1A != m1B (Not same memory address)
m2A != m2B (Not same memory address)
m1A.equals(m1B) = false (Not overwtire equals method)
m2A.equals(m2B) = true (Rewrite equals method)

補充說明 :
This message was edited 2 times. Last update was at 03/12/2010 10:34:56

2 則留言:

  1. 有一段看不懂,想請教前輩:

    //自定型別
    myObject1 m1A = new myObject1();
    myObject1 m1B = new myObject1();
    myObject2 m2A = new myObject2();
    myObject2 m2B = new myObject2();

    //equals的比較
    if (m1A.equals(m1B))
    System.out.println("m1A.equals(m1B) = true");
    else
    System.out.println("m1A.equals(m1B) = false (Not overwtire equals method)");

    if (m2A.equals(m2B))
    System.out.println("m2A.equals(m2B) = true (Rewrite equals method)");
    else
    System.out.println("m2A.equals(m2B) = false");

    這段的結果:
    m1A.equals(m1B) = false (Not overwtire equals method)
    m2A.equals(m2B) = true (Rewrite equals method)

    看不懂m1A、m1B、m2A、m2B的差異,可以請你詳細說明一下嗎?

    回覆刪除
    回覆
    1. m1X (m1A, m1B) 類別並沒有改寫 equals(), 也就是使用預設 Object 的 equals(): 判斷是否為同一個物件.
      m2X (m2A, m2B) 類別改寫了 equals():
      1. if (obj == null) return false; 首先判斷輸入物件如果是 null 則返回 false
      2. if (!(obj instanceof myObject2)) return false; 接著判斷輸入物件是否是此物件類別延伸出來的物件, 不是就返回 false
      3. return this.nNum == ((myObject2) obj).getNum(); 最後判斷兩個物件的 field (nNum) 是否相等, 是就返回 true, 否則 false

      也就是說 m1A 的 equals() 是 Object 來的, 判斷兩個物件是否為同一個.
      因為 m1A 跟 m1B 不是同一個物件, 故 m1A.equals(m2B)=false

      而 m2A 與 m2B 都是 class myObject2 並改寫了 equals(). 故:
      1. m2B 不是 null -> 2. m2B 與 m2A 都是 class myObject2 -> 3. m2B 與 m2A 的 field (nNum) 相等.
      因此 m2A.equals(m2B) = true

      刪除

網誌存檔

關於我自己

我的相片
Where there is a will, there is a way!