可克隆接口的作用是什么?

5
在Java中,Cloneable接口有何作用?Java中的核心对象具有clone()方法。您不能仅覆盖该方法吗?
@Override
public Foo clone(){
    return new Foo(this.x, this.y);
}

请解释为什么您会使用接口。我已经知道如何复制对象的详细信息。我只是不明白为什么要使用接口。


可能是关于Java可克隆性的问题的重复。 - Kenneth Clark
@KennethClark 好吧,那更多是关于克隆的一般性质以及为什么要使用它的问题。 - Daniel K.
2个回答

8
为了回答你的第一个问题,你必须实现Clonable接口才能让clone()方法工作,因为Object类的clone()方法会检查该接口是否被实现,否则它将抛出异常。
使用clone()是一个糟糕的想法。这是Java最初的想法之一,但并没有成功。其中有一些设计问题,包括它通常是浅复制。如果你想要复制或深度复制一个对象,最好创建一个复制构造函数或复制方法来完成,而不使用clone。正确使用clone()很难。
如果你真的想使用clone(),那么请阅读this blog post,它解释了如何使用clone()。基本上,在使用clone()时需要记住5个要点:
1)clone()方法用于在Java中创建对象的副本。为了使用clone()方法,类必须实现java.lang.Cloneable接口,并覆盖java.lang.Object的受保护clone()方法。如果该类没有实现Cloneable接口,则调用clone()方法会导致CloneNotSupportedException。

2) 在Java中,对象克隆时不会调用任何构造函数。

3) Java中clone()方法的默认实现提供了对象的“浅拷贝”,因为它通过创建新实例并通过赋值复制内容来创建对象的副本,这意味着如果您的类包含可变字段,则原始对象和克隆将引用同一个内部对象。这可能很危险,因为对该可变字段所做的任何更改都将反映在原始对象和副本对象中。为避免这种情况,请重写clone()方法以提供对象的深层拷贝。

4) 按照惯例,应通过调用super.clone()方法获取实例的克隆,这有助于保留由clone()方法创建的对象的不变量,即clone!= original且clone.getClass() == original.getClass()。尽管如Javadoc所述,这些不是绝对要求。

5) 对于只包含基元和不可变对象的实例,浅拷贝是可以的,否则,在将其返回给调用者之前,您需要修改一个或多个由super.clone返回的对象的可变字段。


0

正如在Java文档中提到的:

A class implements the Cloneable interface to indicate 
to the Object.clone() method that it is legal for that method 
to make a field-for-field copy of instances of that class.

具体来说:

Invoking Object's clone method on an instance that does not 
implement the Cloneable interface results in the exception
CloneNotSupportedException being thrown.

如果您有任何问题,请告诉我。


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