为什么不在内部重写.clone?

时间:2015-11-02 14:21:12

标签: java clone

我理解Java克隆是如何工作的以及反对使用它的论据。让我们说无论如何我已经死了。

为了方便起见,我想为类Foo编写一个克隆方法,如下所示:

@Override
public Foo clone(){
    Foo f = (Foo)super.clone();
    //Replace mutable fields
    return f;
}

据我所知,这是安全的。但是,我注意到API中的Cloneable类不会这样做。这有什么原因,是不是很糟糕?

3 个答案:

答案 0 :(得分:17)

在Java 5之前,根本不允许使用协变返回类型,因此Foo clone()甚至不会编译。 由于很久以前已经编写了很多Cloneable类,这可能是大多数情况的原因。

我怀疑新类没有使用它只是因为已知clone()非常少,而当人们很少使用它时,他们甚至不认为他们可以使用它。他们找到了一些“如何实现clone()”的问题并以老式的方式编写代码。

答案 1 :(得分:3)

Object.clone()创建一个新对象,其中所有字段都与原始字段具有相同的值。对于引用类型的字段,这意味着新字段只是对与原始字段相同的对象的引用。它没有clone个字段。因此,在许多情况下,默认实现将导致共享数据,这可能是不期望的。例如,如果ArrayList.clone()使用了默认实现,那么最终会有两个ArrayList个实例共享相同的后备数组。

如果对象的所有字段都是不可变的,那么简单地将super.clone()的结果转换为适当的类型可能是个好主意。

答案 2 :(得分:3)

嗯,这绝对不是一个糟糕的风格,事实上,自从java 1.5发布以来你最好这样做,因为协变返回类型是 作为泛型的一部分在1.5版中引入,通过这样做,您可以更容易地使用API​​(不需要进行转换)。

source(Effective java 2nd edition)。