为什么界面中没有.clone()指定方法java.lang.Cloneable?
这对我来说是一种耻辱,但我不知道:
您应该使用clone来复制数组,因为这通常是最快的方法.
正如Josh Bloch在本博客中所述:http://www.artima.com/intv/bloch13.html
我总是用System.arraycopy(...).这两种方法都是原生的,所以可能没有深入到我无法弄清楚的库的来源,为什么会如此.
我的问题很简单:为什么它是最快的方式?
有什么区别这里
解释了不同之处,但它没有回答为什么Josh Bloch认为System.arraycopy?clone()最快的方式.
我正在阅读正确执行数组的深层副本,但是我对如何#clone()实现它感到困惑.它是java.lang.Object该类的成员,但如果您阅读了javadoc:
首先,如果此对象的类未实现Cloneable接口,则抛出CloneNotSupportedException.
那么为什么要首先定义clone那里的方法呢?当然,如果方法只能在存在接口时使用,则将该方法放在接口中.该Cloneable接口本身是空的; 它只是Java使用的标记接口,以确保使用该clone方法是合法的.
这样做也会消除使用泛型来确保类型安全的能力:
class Foo implements Cloneable { // Valid.
@Override
public Object clone() throws CloneNotSupportedException {
// ...
}
}
class TypeSafeFoo implements Cloneable<TypeSafeFoo> { // Not valid.
@Override
public TypeSafeFoo clone() throws CloneNotSupportedException {
// ...
}
}
Run Code Online (Sandbox Code Playgroud)
为什么Java以这种方式完成它?我确信他们有合理的理由,但我似乎无法弄明白.
Cloneable在Java中本质上是破碎的.具体来说,我对界面的最大问题是它需要一种不定义方法本身的方法行为.因此,如果遍历Cloneable列表,则必须使用反射来访问其定义的行为.但是,在Java 8中,我们现在有默认方法,现在我问为什么没有默认clone()方法Cloneable.
我理解为什么接口不能默认Object方法,但是,这是一个明确的设计决策,因此可以做出异常.
我有点想到弃用Object.clone()并将其内部代码更改为:
if(this instanceof Cloneable) {
return ((Cloneable) this).clone();
}
else {
throw new CloneNotSupportedException();
}
Run Code Online (Sandbox Code Playgroud)
并继续前进任何魔法使其clone()成为默认方法Cloneable.这并没有真正解决,clone()仍然可以很容易地错误地实现,但这本身就是另一个讨论.
据我所知,这种变化将完全向后兼容:
clone()但未实现的类Cloneable(为什么?!)在技术上仍然可以(即使在功能上不可能,但这与以前没有什么不同).clone()但实现的类Cloneable在其实现上仍将起相同的作用.clone(),但确实实现Cloneable(为什么?!)的类现在将遵循规范,即使它在功能上并不完全正确.Object.clone()仍然可以在功能上工作.super.clone()即使它正在引用,它在功能上仍然是相同的Object.clone().更不用说这将解决一个巨大的问题Cloneable.虽然繁琐且仍然容易错误地实现,但它将解决界面的巨大面向对象问题.
我能看到的唯一问题是那些实现Cloneable没有义务覆盖的问题clone(),但这与以前没有什么不同.
这已在内部进行过讨论,但从未取得成果吗?如果是这样,为什么?如果是因为接口不能默认使用Object方法,那么在这种情况下做出异常是否有意义,因为所有继承Cloneable的对象都是期待clone()的?
我试图了解 Object.clone() 在 Java 中是如何工作的。我发现了以下事实:
Cloneable接口以向 Object.clone() 方法指示该方法对该类的实例进行逐字段复制是合法的。Object方法会导致抛出异常。cloneCloneableCloneNotSupportedExceptionCloneable接口不包含该clone方法。因此,实现Cloneable不负责因未实现而引发任何错误/异常clone()。Object.clone()是一个本机方法,它从此cpp方法中调用 并抛出。JVM_Clone jvm.cppCloneNotSupportedException疑点:
Q1. 为什么Java设计者会做出这样的设计选择并这样实现呢?为什么不在其自身clone()中进行定义Cloneable,如果实现类没有提供clone().
Q2。Cloneable为什么要在运行时检查实例是否实现?
Q3。有什么具体原因要在本机代码中检查它吗?
Q4。奇怪的是Object它本身并没有实现Cloneable,但提供了一个实现clone(),它反过来检查是否有任何类实现了Cloneable实现clone()。理想情况下,不应该Object实现Cloneable(声明clone())然后提供实现吗clone()?
PS:我知道在一个问题中提出多个问题是一个坏主意。但这些都是密切相关的问题。我很可能会问一个问题,比如“为什么不Cloneable包含clone()?” 但是,我觉得,为了更好地回答这个疑问,必须涵盖这一设计决策的各个微妙方面。我努力思考更多,并提出了可能的不同微妙方面,并逐点明确地询问它们,以便回答者不会错过它们并给出总体完整的答案。
在这个错误报告中,Doug Lea写道(指的是JDK 5.0的预发布版本):
虽然
CopyOnWriteArraySet声明Cloneable,它没有界定公共clone方法.
但它最终会CopyOnWriteArraySet完全没有实现Cloneable接口!(在Java SE 6,7和8中都是如此)
如何CopyOnWriteArraySet从不同的CopyOnWriteArrayList关于克隆?有没有人想要克隆它?
PS我明白clone()不推荐这CopyOnWriteArraySet是基于CopyOnWriteArrayList内部的.