2014-09-12 71 views
4

對於下面的類,我知道c1.equals(c3)返回false,因爲c1.clone()創建指向同一對象的不同引用。但爲什麼carList1.equals(carList2)返回true?爲什麼它不同於c1.equals(c3)?提前謝謝了!Java clone()和equals()檢查

class Car implements Cloneable { 
    private String plate; 
    private double maxSpeed;  
    public Car(String lp, double max) { 
     license = lp; 
     maxSpeed = max; 
    } 
    public static void main(String[] args) throws Exception{ 
     Car c1 = new Car("ABC123", 150.0); 
     Car c2 = new Car("ABC123", 150.0); 
     Car c3 = (Car) c1.clone(); 
     ArrayList<Car> carList1 = new ArrayList<Car>(); 
     carList1.add(c1); 
     carList1.add(c2); 
     ArrayList carList2 = (ArrayList) carList1.clone(); 
    } 
} 

回答

5

ArrayListclone執行淺拷貝,即,它不包含克隆的ArratList內的元素,它只是複製引用。這就是爲什麼equals返回true,因爲它不比較ArrayList對象的引用,它比較列表中的元素。

公共對象的clone()

返回此ArrayList實例的淺表副本。 (元素 本身不會被複制。)

公共布爾等於(對象O)

比較指定的對象與列表是否相等。返回 當且僅當指定的對象也是一個列表時,兩個列表 具有相同的大小,並且兩個 列表中的所有相應元素對都相等。 (如果(e1 == null? e2 == null:e1.equals(e2)),兩個元素e1和e2是相等的。)換句話說,兩個元素定義爲 如果它們包含相同元素相同的順序。

在另一方面,租車,假設你沒有覆蓋其equals方法,只是成員相比,使用對象的默認實現::等於,其中比較對象的引用,因此克隆車是不是等於原來的。

+1

此外,如果'Car'有一個明智的' equals()'實現,而不是依賴從Object繼承的那個,那麼'c3.equals(c1)'也是如此。 – biziclop 2014-09-12 10:08:03

+0

但我認爲對象的克隆也是淺拷貝?另外在這裏這個問題http://stackoverflow.com/questions/1574960/java-clone-and-equality-checks,兩個數組的equals()返回false。我很困惑。 – user3735871 2014-09-12 10:09:58

+0

@ user3735871對象的克隆是您必須實現的東西。不管它是否淺薄都沒關係,因爲你並不是重寫equals方法。 – Eran 2014-09-12 10:12:51

0

您的Car班級尚未重寫equals()。所以它僅僅通過對象標識來評估相等性,即默認行爲 - 與==運算符相同。

在另一方面,ArrayList的覆蓋equals(),它通過對列表中的所有元素調用equals()做的。如果列表的元素全部相等,那麼列表是平等的。而且,如提到的另一個答案,clone()方法會創建一個新列表,其中包含與原始對象(不是副本)相同的相同的對象。

0

ArrayList沒有equals()方法。它擴展了AbstractList,它定義/實現equals()clone()僅複製引用,因此兩個列表中的對象都是相同的。 從Oracle文檔:equals()做到這一點:

比較指定對象與此列表是否相等。返回 當且僅當指定的對象也是一個列表時,兩個列表 具有相同的大小,並且兩個 列表中的所有相應元素對都相等。 (如果(e1 == null? e2 == null:e1.equals(e2)),兩個元素e1和e2是相等的。)換句話說,兩個元素定義爲 如果它們包含相同元素相同的順序。這個 實現首先檢查指定的對象是否是這個列表。如果 那麼,它返回true;如果不是,則檢查指定的對象是否爲 列表。如果不是,則返回false;如果是這樣,它將遍歷這兩個列表, 比較相應的元素對。如果任何比較返回 false,則此方法返回false。如果任一迭代器在另一個迭代器之前耗盡了 個元素,它將返回false(因爲列表的長度不等,爲 );否則當迭代 完成時它將返回true。

0

這一切都取決於equals(...)的實施。只要您不覆蓋它,clone()函數將不會複製所有內容(在Clonable JavaDoc中推薦)。

所以,你應該做兩兩件事:

  1. 覆蓋clone()
  2. 覆蓋equals()(和hashCode(),而你在它)