为什么Java 8中Cloneable中没有默认的clone()
Java中的为什么Java 8中Cloneable中没有默认的clone(),java,java-8,clone,cloneable,default-method,Java,Java 8,Clone,Cloneable,Default Method,Java中的Cloneable本质上是不可靠的。具体地说,我对接口的最大问题是,它需要一个不定义方法本身的方法行为。因此,如果遍历一个Cloneable列表,您必须使用反射来访问它定义的行为。然而,在Java8中,我们现在有了默认方法,现在我问为什么在Cloneable中没有默认的clone()方法 然而,我理解为什么这是一个明确的设计决策,因此可以做出例外 我有点想象不推荐Object.clone(),并将其内部代码更改为如下内容: if(this instanceof Cloneable)
Cloneable
本质上是不可靠的。具体地说,我对接口的最大问题是,它需要一个不定义方法本身的方法行为。因此,如果遍历一个Cloneable
列表,您必须使用反射来访问它定义的行为。然而,在Java8中,我们现在有了默认方法,现在我问为什么在Cloneable
中没有默认的clone()
方法
然而,我理解为什么这是一个明确的设计决策,因此可以做出例外
我有点想象不推荐Object.clone()
,并将其内部代码更改为如下内容:
if(this instanceof Cloneable) {
return ((Cloneable) this).clone();
}
else {
throw new CloneNotSupportedException();
}
继续使用clone()
中的任何魔法,作为Cloneable
中的默认方法。这并不能真正解决clone()
仍然很容易错误实现的问题,但这本身就是另一个讨论
就我所知,此更改将完全向后兼容:
clone()
但未实现Cloneable
(为什么?!)的类在技术上仍然可以(即使功能上不可能,但这与以前没有什么不同)clone()
,但确实实现了Cloneable
的类在其实现上仍将起相同的作用clone()
,但实现了Cloneable
(为什么?!)的类现在将遵循规范,即使它在功能上不完全正确Object.clone()
的方法在功能上仍然有效super.clone()
Cloneable
所面临的巨大问题。虽然它很乏味,而且很容易错误地实现,但它将解决一个巨大的面向对象接口问题
我能看到的唯一问题是那些实现Cloneable
的人没有义务重写clone()
,但这与以前没有什么不同
这是否已经在内部讨论过,但从未取得成果?若然,原因为何?如果是因为接口不能默认对象方法的原因,那么在这种情况下做一个例外是否有意义,因为所有继承
Cloneable
的对象都需要clone()
?您的问题有点宽泛,而且更具讨论性,但我可以解释一下这一点
用有效的Java语言™, 约书亚·布洛赫(Joshua Bloch)提供了有关情况的详细情况。他一开始就带着一点历史背景Cloneable
Cloneable接口旨在作为对象的mixin接口
宣传他们允许克隆。不幸的是,它未能达到这一目的。它的主要缺陷是缺少克隆方法,并且对象的克隆方法受到保护。如果不诉诸反射,就不能仅仅因为对象实现了Cloneable而对其调用clone方法
并继续进行推理
[Cloneable]确定对象的受保护克隆实现的行为:如果类实现了Cloneable,则对象的clone方法返回对象的逐字段副本。。。这是对接口的一种非常非典型的使用,不需要进行仿真。通常,实现接口说明类可以为其客户机做些什么。在可克隆的情况下,它修改超类上受保护方法的行为
及
如果实现可克隆接口对类有任何影响
类及其所有超类必须遵守一个相当复杂、不可执行且
稀薄记录的协议。由此产生的机制是语言外的:它创建一个对象而不调用构造函数
这方面有很多细节,但只需注意一个问题:
克隆体系结构与引用可变对象的final字段的正常使用不兼容
我认为这足以说明为什么不在接口中使用
default
方法进行克隆。正确地实现它将非常复杂。我的经验可能远不是主流,但我使用clone()
并支持当前的Cloneable
设计。也许最好将其作为注释,但是Cloneable
早在注释出现之前就出现了。我的观点是,Cloneable
是一个低级的东西,任何人都不应该做类似于obj instanceof Cloneable
的事情。如果在某些业务逻辑中使用Cloneable
,最好声明自己的接口或抽象类,将clone()
公开,并在所有业务逻辑对象中实现它。有时您可能不想公开clone()
,而是创建自己的方法,在内部使用clone()
例如,考虑到你有一个名字对象的层次结构,其中名字在构造之后不能被改变,但是你想允许用新的名字克隆它们。您可以创建一些抽象类,如下所示:
public abstract class NamedObject implements Cloneable {
private String name;
protected NamedObject(String name) {
this.name = name;
}
public final String getName() {
return name;
}
public NamedObject clone(String newName) {
try {
NamedObject clone = (NamedObject)super.clone();
clone.name = newName;
return clone;
}
catch(CloneNotSupportedException ex) {
throw new AssertionError();
}
}
}
在这里,即使您实现了Cloneable
,您也希望使用clone()
,但不希望公开它。相反,您提供了另一种方法,允许使用其他名称进行克隆。因此,在Cloneable
中使用publicclone()
将不必要地污染类的公共接口
我使用Cloneable
的另一个例子是Spliterator.trySplit()
的实现。请参阅返回给定数量常量对象的简单拆分器的说明。它有四个专门化(对象、整数、长整数和双精度),但这要归功于<