如何在Java中克隆对象。

4
我希望创建一个具有相同父类的对象列表/数组,然后我将用它作为参考。但我不知道如何克隆这些对象以创建新对象。
以下是示例:
BigFoo a;
SmallFoo b;
ChickenFoo c;
List<Foo> foos;
foos.add(a);
foos.add(b);
foos.add(c);

Foo foo = foos.get(1).clone();

但是在Java中,我发现默认函数中没有克隆函数。我想知道这是如何实现的?

2个回答

4
一般建议:使用复制构造函数。事实上,只有类本身知道如何创建自己的克隆。没有任何类能够克隆另一个类的实例。思路如下:
public class Foo {
  public List<Bar> bars = new ArrayList<Bar>();
  private String secret;

  // Copy constructor
  public Foo(Foo that) {
    // new List
    this.bars = new ArrayList<Bar>();

    // add a clone of each bar (as an example, if you need "deep cloning")
    for (Bar bar:that.bars) {
      this.bars.add(new Bar(bar));
    }

    // clone the secret value
    this.secret = new String(that.secret);
  }

  // ...

}

如果我们想克隆一个foo,我们只需基于foo创建一个新的对象:

Foo clonedFoo = new Foo(foo);

这是克隆实例的推荐方法。


复制构造函数与继承很好地配合。考虑一个子类。

 public ChildFoo extends Foo {

   private int key;

   public ChildFoo(ChildFoo that) {
     super(that);
     this.key = that.key;
   }
 }

Foo有一个复制构造函数,而ChildFoo只是从自己的复制构造函数中调用它。

你的例子是可行的,但不建议使用。会发生什么:

 Foo a = new Foo();
 ChildFoo b = new ChildFoo(a);  

这将需要在ChildFoo上添加构造函数,例如:
 public ChildFoo(Foo that) {
     // call the copy constructor of Foo -> no problem
     super(that);

     // but how to initialize this.key? A Foo instance has no key value!
     // Maybe use a default value?
     this.key = 0;
 }

从技术上讲,这不是一个挑战,但b并非a的克隆,因为这两个对象的类型不同。因此,这个例子不是“克隆”。


这将适用于相同的类对象。但是对于它的继承类呢?Foo a = new Foo(); ChildFoo child = new ChildFoo(a); 这样可以吗? - Fugogugo
拷贝构造函数只有在您知道要复制的对象的确切类型时才能起作用。如果您需要克隆一个List,您将使用哪个类构造函数(ArrayList、LinkedLink等)? - Steve Kuo
@Steve - List 接口没有 clone 方法,那你怎么办呢?我们不能克隆 接口 - Andreas Dolk

1
一种简单的方法是使用JSON映射器(Jackson或Gson),将对象写成字符串,然后通过使用该字符串创建克隆对象。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接