繁体   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