【发布时间】:2016-03-11 08:57:39
【问题描述】:
Java 中的Cloneable 天生就被破坏了。具体来说,我对接口的最大问题是它需要一个不定义方法本身的方法行为。因此,如果遍历 Cloneable 列表,您必须使用反射来访问其定义的行为。但是,在 Java 8 中,我们现在有了默认方法,现在我问为什么 Cloneable 中没有默认的 clone() 方法。
我理解为什么interfaces cannot default Object methods,但是,这是一个明确的设计决定,因此可以例外。
我有点想弃用 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()即使引用Object.clone(),其功能仍然相同。
更不用说这会解决Cloneable 的一个巨大问题。虽然繁琐并且仍然很容易错误地实现,但它可以解决接口的一个巨大的面向对象问题。
我能看到的唯一问题是实现Cloneable 的那些没有义务覆盖clone(),但这与以前没有什么不同。
这是否在内部讨论过,但从未实现?如果是这样,为什么?如果是因为接口不能默认 Object 方法的原因,那么在这种情况下进行异常处理是否有意义,因为所有继承 Cloneable 的对象都期待 clone() 反正?
【问题讨论】:
-
我记得在某处(来自官方来源)读到
Cloneable已损坏,甚至不值得修复。但是您的默认方法的问题之一是使用this在那里很棘手。 -
基本上,@Tunaki 所说的是正确的。这种跳圈的复杂性并不存在。我们选择将 {时间、精力、复杂性} 预算投入到产生更多价值的其他领域。
-
创建这样的
default方法是没有意义的。如果java.lang.Object中有一个方法和interface中有同名和签名的default方法,则java.lang.Object中声明的方法仍然会因不合格的调用而获胜。如果java.lang.Object中的方法保持protected,则所有Cloneable实现都将强制将该方法重新声明为public,而将其更改为public仍需要调整现有实现。换句话说,结果与在Cloneable接口中定义abstract clone()方法没有区别。 -
它不完全兼容 - 它会在类具有非公共
clone方法的地方中断,因为它会尝试用protected方法覆盖public方法(例如如果需要克隆一个类,但只能克隆它自己)
标签: java java-8 clone cloneable default-method