Java 为什么不在Overrided.clone内部强制转换?

Java 为什么不在Overrided.clone内部强制转换?,java,clone,Java,Clone,我了解Java克隆的工作原理以及反对使用它的理由。让我们假设我已经下定决心要用它了 为了方便起见,我想为类Foo编写一个clone方法,如下所示: @Override public Foo clone(){ Foo f = (Foo)super.clone(); //Replace mutable fields return f; } 据我所知,这是安全的。然而,我注意到API中的可克隆类并没有做到这一点。这有什么原因吗?它的风格不好吗?早在Java 5之前,协变返回类

我了解Java克隆的工作原理以及反对使用它的理由。让我们假设我已经下定决心要用它了

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

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

据我所知,这是安全的。然而,我注意到API中的可克隆类并没有做到这一点。这有什么原因吗?它的风格不好吗?

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

我怀疑较新的类之所以不使用它,仅仅是因为
clone()
非常少,而且当人们很少使用它时,他们甚至认为自己无法使用它。他们发现了一些“如何实现克隆()”的问题,并以老式的方式编写代码。

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


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

Hmm,这绝对不是一个坏样式,事实上,自java 1.5发布以来最好这样做,因为协变返回类型是 在1.5版中作为泛型的一部分引入,通过这样做,您使API更易于使用(不需要强制转换)


源代码(有效的java第二版)。

请注意,只有这样使用它时才有用:
Foo-Foo=。。。;Foo bar=Foo.clone()
。API对于
clone()
的预期用途非常模糊,但它确实指出:
通常,这意味着复制构成被克隆对象内部“深层结构”的任何可变对象,并将对这些对象的引用替换为对副本的引用。
,因此,
clone()
理想情况下应该返回一个深度副本。理想情况下,但不一定……如果字段都是不可变的,那么深度副本和浅层副本之间没有区别。这是真的,但这与问题有什么关系?我有点迷路了它回答了这个问题。之所以不简单地执行
(MyClass)super.clone()
,是因为这是一个浅拷贝,而通常需要一个深拷贝。我说过,如果深度复制和浅层复制没有区别的话,可以这样做。哦,我明白了。公平地说,我认为问题纯粹是关于为什么我们在重写
clone()
时不使用协变返回类型,而不是关于强制转换
super.clone()
。很老的一句话“它已经破产了,甚至没有人试图浪费时间来修复它”。