问题描述
您的问题有些广泛,需要更多讨论,但我可以就此问题提供一些启示。
在《 有效的Java™》中 ,Joshua Bloch给出了有关情况的简要说明。他的开场白有着悠久的历史Cloneable
Cloneable接口旨在用作对象的混合接口,以宣告它们允许克隆。不幸的是,它不能达到这个目的。它的主要缺陷是缺少克隆方法,并且对象的克隆方法受到保护。如果不依靠反射,就不能仅仅因为对象实现Cloneable而在对象上调用clone方法。
并继续推理
[Cloneable]决定对象受保护的克隆实现的行为:如果一个类实现了Cloneable,则对象的clone方法将返回该对象的逐字段副本…这是一种非常不典型的接口使用方式,而不是被仿真的接口。通常,实现接口会说明类可以为其客户端执行的操作。在Cloneable的情况下,它会修改超类上受保护方法的行为。
和
如果实现Cloneable接口对一个类有任何影响,则该类及其所有超类必须服从一个相当复杂,不可执行且内容简短的协议。由此产生的机制是语言外的:它无需调用构造函数即可创建对象。
这涉及很多细节,但仅需注意一个问题:
克隆体系结构与引用可变对象的final字段的正常使用不兼容。
我认为这足以阻止default
在接口中进行克隆。正确实现它将极其复杂。
解决方法
Cloneable
Java固有地被破坏了。具体来说,我与接口有关的最大问题是,它期望方法行为无法定义方法本身。因此,如果遍历Cloneable
列表,则必须使用反射来访问其定义的行为。但是,在Java
8中,我们现在有了默认方法,现在我问为什么在中没有默认clone()
方法Cloneable
。
我知道为什么接口不能使用默认的Object方法,但是,这是一个明确的设计决定,因此可以进行例外处理。
我有点设想过时Object.clone()
,并将其内部代码更改为以下内容:
if(this instanceof Cloneable) {
return ((Cloneable) this).clone();
}
else {
throw new CloneNotSupportedException();
}
并且继续进行任何魔术创造clone()
的事情,作为中的默认方法Cloneable
。这并不能解决clone()
仍然可以很容易地错误实现的问题,但这本身就是另外一个讨论。
据我所知,此更改将完全向后兼容:
- 当前覆盖
clone()
但未实现的类Cloneable
(为什么?!)在技术上还是可以的(即使在功能上是不可能的,但这和以前没什么不同)。 - 当前覆盖
clone()
,但是实现Cloneable
了的类在其实现上仍将发挥相同的作用。 - 当前未覆盖
clone()
,但实现了Cloneable
(WHY ?!)的类现在将遵循规范,即使它在功能上并不 完全 正确。 - 使用反射并引用的那些在
Object.clone()
功能上仍将起作用。 super.clone()
即使在引用时,在功能上仍然相同Object.clone()
。
更不用说这将解决一个巨大的问题Cloneable
。尽管繁琐并且仍然容易错误地实现,但是它将通过接口解决一个巨大的面向对象的问题。
我能看到的唯一问题是那些实现Cloneable
者没有义务重写clone()
,但这与以前没有什么不同。
是否在内部进行过讨论,但从未实现过?如果是这样,为什么?如果是由于接口无法默认Object方法的原因,那么在这种情况下将异常设置为有意义,因为所有继承Cloneable
的对象clone()
无论如何都期待着?