簡體   English   中英

將 ArrayList 元素克隆到同一個 ArrayList

[英]Clonning ArrayList element to the same ArrayList

我有一個包含對象的ArrayList (這個對象是類,每個對象都包含大量的信息,正是這些對象代表了大型發電機,因此無法逐一復制屬性)。

例子:

ArrayList arr = {ob1, ob2, ob3, ob4, ob5}

所以我嘗試做的是將對象(ob1)克隆到位置 5。

arr.set(4, arr.get(0));

但不知何故,這樣做,ob5 不是復制 ob ob1,它是 ob1,所以如果我改變 ob5,ob1 也會改變。

這是 ArrayLists 固有的東西嗎? 如果我改用 Lists 有什么區別嗎?

ArrayList 保存引用是的。 但是你可以克隆它(注意!但它將是淺拷貝 - 它不會克隆內部對象https://stackoverflow.com/a/13434779/1111527

private class JustToCheck implements Cloneable {

    @Override
    public Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
}

然后像這樣使用

JustToCheck ob1 = new JustToCheck();
JustToCheck ob2 = ob1;

List<JustToCheck> arr = new ArrayList<JustToCheck>();
arr.add(ob1);
arr.add(ob2);

System.out.println(arr.get(0).toString() + ": " + arr.get(1).toString());

try {
    arr.set(1, (JustToCheck) ob1.clone());
} catch (CloneNotSupportedException e) {
    e.printStackTrace();
}

System.out.println(arr.get(0).toString() + ": " + arr.get(1).toString());

輸出是

example$JustToCheck@1c39a2d: example$JustToCheck@1c39a2d
example$JustToCheck@1c39a2d: example$JustToCheck@bf2d5e


PS - 我已經檢查了答案https://stackoverflow.com/a/13434813/1111527 中的問題

有一些不可變的類

Java6

String a = new String("a");
String b = a;
b += "b"; 
System.out.println("a = " + a); // a = a
System.out.println("b = " + b); // b = ab

這是因為您正在執行卷影復制而不是深層復制。

淺拷貝:如果在Obj-1上執行淺拷貝,則復制它但不復制其包含的對象。 包含的對象Obj-1Obj-2受克隆 Obj-2 更改的影響 當類實現 java.lang.Cloneable 接口時,Java 默認支持對象的淺層克隆。

深副本:如果一個深拷貝是在執行obj-1所示,那么不僅obj- 1已經被復制,但對象包含在它已被復制為好 序列化可用於實現深度克隆。 通過序列化進行深度克隆的開發速度更快且更易於維護,但會帶來性能開銷。 來源

深拷貝的一個例子:

class Student implements Cloneable {
  //Contained object
  private Subject subj;
  private String name;

  public Subject getSubj() {..}
  public String getName() {..}

  public Object clone() {
    //Deep copy
    Student s = new Student(name, subj.getName());
    return s;
  }
}

在 Java 中的任何地方都是如此。 除非您明確這樣做,否則不會復制任何內容。 (確實,有些對象是故意無法復制的。)

您需要制作ElectricGenerator的副本。 最常見的選項是引入復制構造函數或實現克隆方法。 然而,這兩種解決方案都需要復制所有這些屬性。

一旦你有了它,你就可以做到

//copy constructor
arr.add( new ElectricGenerator( arr.get( 0 ) ) );
//clone
arr.add( arr.get( 0 ).clone() );

另一種方法是序列化/反序列化對象

這不符合 ArrayList,這是一個 java 特性。 不創建新對象,只傳遞一個引用。 因此 ArrayList 存儲了兩個引用。 您必須使用對象的 .clone() 方法。

arr.set(4, arr.get(0).clone());

這將創建對象的新副本,即使此副本將是淺的。 如果需要,您必須覆蓋 clone 方法以使其成為深層副本。

不,這是因為在 Java 中,您創建了對對象的引用,因此即使您不使用 ArrayList 並執行以下操作:

String a = new String("a");
String b = a;

b += "b";

a 和 b 都等於“ab”。

(例外是像 int 這樣的基本類型(但不是 Integer 的實例,有不同的東西))。

所以你的問題的答案在這里: 如何通過值復制對象,而不是通過引用和這里: http : //www.itcsolutions.eu/2010/12/29/tutorial-java-6-4-2-how -to-copy-values-of-an-array-into-another-array/

該列表僅包含指向對象的指針..

如果您將 ob1 移動到 ob5 會發生什么,您告訴列表將指針指向 ob5 的指針所在的 ob1,因此丟失指向 ob5 的指針並復制指向 ob1 的指針...

您將需要創建一個包含重復值的其他對象,然后將此對象分配給位置 4

對象變量不同於原始數據類型。

int x = 2;
int y = x;

x 和 y 指的是不同的內存位置。

MyClass x = new MyClass();
MyClass y = x;

x 和 y 引用相同的內存位置,但該位置有兩個引用。 對其中一個所做的任何更改都會改變另一個。 解決這個問題的方法是實現Cloneable並使用.clone()方法。

shallow copying創建同一個類的新實例,並將所有字段復制到新實例並返回它。 Object 類提供了一個 clone 方法,並提供了對淺拷貝的支持。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM