HOWTO · Java

在 Java 中深拷貝 ArrayList

本文介紹如何在 Java 中深拷貝 ArrayList。

本頁內容

在 Java 語言中,如果要複製 ArrayList,可以有兩種方法。進行深拷貝或淺拷貝。

在深拷貝中,將建立一個全新的物件,因此,舊物件狀態的變化不會反映新建立的例項中的任何更改。

在淺拷貝中,我們建立一個新物件,該物件具有對現有物件的引用。因此,舊物件狀態的任何更改都將反映在新建立的例項中。

該圖更好地說明了以上兩個定義:

深拷貝與淺拷貝

什麼是深拷貝

從現有物件建立新物件稱為深拷貝。這種型別的拷貝沒有對當前物件的任何引用。深拷貝是一項迭代任務。它以遞迴方式將內部成員變數和物件複製到新例項中。

這種型別的克隆將複製所有巢狀物件,並且在源和副本之間不保留任何引用連結。此克隆精確地複製了所有原始(位元組,短型,整型)和非原始(字串,陣列,類)資料型別。

如果要深拷貝物件,請從 Object 類覆蓋 Cloneable 介面的 clone() 方法。

這是用 Java 深拷貝 ArrayList 的程式碼示例:

package deepVsShallowCopy;

public class Car implements Cloneable {
  String name;

  public String getName() {
    return name;
  }

  public void setName(String name) {
    this.name = name;
  }

  public Car(String name) {
    this.name = name;
  }

  @Override
  public Car clone() throws CloneNotSupportedException {
    Car newCar = (Car) super.clone();
    newCar.setName(newCar.getName());
    return newCar;
  }
}

在上面的 POJO 類中,應該重寫 clone 方法以及 gettersetter 方法。clone() 方法會丟擲 CloneNotSupportedException,我們應該在被覆蓋的方法中丟擲該異常。

我們應該實現我們的版本以克隆現有物件。我們必須將 Car 類的所有成員變數複製到新例項中。

以下是用於深複製 ArrayList 的驅動程式類實現:

package deepVsShallowCopy;

import java.util.ArrayList;
import java.util.List;

public class DeepCopyArrayList {
  public static void main(String[] args) throws CloneNotSupportedException {
    // instantiate car instance
    Car oldCar = new Car("Ambassador");
    // instantiate an arraylist
    List<Car> oldList = new ArrayList<Car>();
    // add oldCar object into the list
    oldList.add(oldCar);

    // instantiate newList
    List<Car> newList = new ArrayList<Car>();
    // add object created using clone() into list
    newList.add(oldList.get(0).clone());
    // rename field in newList car element
    newList.get(0).setName("Rolls Royce");

    System.out.println("oldName : " + oldList.get(0).getName()); // oldName : Ambassador
    System.out.println("newName : " + newList.get(0).getName()); // newName : Rolls Royce
  }
}

在上述實現中,呼叫了 Car 類的過載 clone() 方法,該方法將返回一個全新的例項。並將這個新建立的例項新增到 ArrayList 中。

當我們在新建立的物件中進行一些操作時,這不會影響舊物件的引用。

另外,如果我們想在 ArrayList 中單獨進行迭代,則將在 Car 的物件上呼叫 clone() 方法,即

for (Car c : oldList) {
  newList.add(c.clone());
}