为什么克隆人不反对?

内容来源于 Stack Overflow,并遵循CC BY-SA 3.0许可协议进行翻译与使用

  • 回答 (2)
  • 关注 (0)
  • 查看 (20)

人们普遍认为CloneableJava中的接口中断了。

因此,我的问题是:为何至今仍未受到反对?如果核心Java团队已经决定了它是坏的,那么他们也必须考虑反对意见。他们反对这样做的理由是什么。

提问于
用户回答回答于

关于添加clone()方法Cloneable这样就不再是无用的了。会议结束时通过了“不会解决”的决议,理由如下:

孙的技术审查委员会(TRC)详细审议了这个问题,并建议不要接受除了改进当前可克隆接口的文档以外的任何其他操作。建议全文如下: 现有的Java对象克隆API存在问题。java.lang.Object上有一个受保护的“克隆”方法,还有一个接口java.lang.Cloneable。这样做的意图是,如果一个类想让其他人克隆它,那么它应该支持cloneable接口,并用一个公共克隆方法覆盖默认的受保护的克隆方法。不幸的是,由于时间迷雾中容易丢失的原因,克隆接口没有定义克隆方法。 这种组合会造成相当多的混乱。有些类声称支持克隆,但意外地忘记了支持克隆方法。开发人员对克隆人应该如何工作以及克隆人应该做什么感到困惑。 不幸的是,向cloneable添加“克隆”方法将是一个不兼容的更改。它不会破坏二进制兼容性,但会破坏源代码兼容性。坊间证据表明,在实践中,有许多类支持可克隆接口,但无法提供公共克隆方法的情况。经过讨论,TRC一致建议我们不应该修改现有的可克隆接口,因为兼容性的影响。 另一项建议是添加一个新的接口java.lang.PubliclyCloneable,以反映cloneable最初的预期用途。真相与和解委员会以5比2的多数票反对这一做法。主要担心的是,这会给已经混乱的图片增加更多的混乱(包括拼写混淆!)。TRC一致建议在现有的cloneable界面上添加更多文档。以便更好地描述如何使用它,并描述实现者的“最佳实践”。

所以,虽然这不是直接关于弃用,不让克隆人“不推荐”的原因是技术审查委员会决定修改现有文档就足够了使这个界面有用。他们就这么做了。直到Java 1.4,Cloneable记录如下:

一个类实现了cloneable接口,以向Object.clon()方法指示该方法对该类实例进行字段对字段复制是合法的。 试图克隆不实现可克隆接口的实例将引发异常CloneNotSupportdException。 接口cloneable没有声明任何方法。

自从Java1.4(于2002年2月发布)到当前版本(Java8),它看起来如下所示:

一个类实现了cloneable接口,以向Object.clon()方法指示该方法对该类实例进行字段对字段复制是合法的。在不实现cloneable接口的实例上调用Object的克隆方法将导致抛出异常CloneNotSupportdException。 按照约定,实现此接口的类应该用公共方法覆盖Object.Clonent(受保护)。有关重写此方法的详细信息,请参见Object.Clan()。 请注意,此接口不包含克隆方法。因此,不可能仅仅依靠对象实现这个接口这一事实来克隆对象。即使克隆方法被反思广益地调用,也不能保证它会成功。

用户回答回答于

“为什么不是Cloneable不赞成?“(或者说,为什么不是?X不赞成,对任何X)是没有多少人注意到反对他们。

大多数最近被废弃的东西都被废弃了,因为有一个特定的计划来删除它们。例如,addPropertyChangeListenerremovePropertyChangeListener方法日志管理器成在JavaSE 8中被废弃以便在JavaSE 9中删除它们。(原因是它们不必要地复杂了模块之间的依赖关系

没有类似的计划CloneableObject.clone()...

一个更长的答案将涉及讨论进一步的问题,例如人们可能期望这些API会发生什么,如果不推荐这些API会为平台带来什么成本或收益,以及当一个API被废弃时,会向开发人员传达什么。我在最近的JavaOne演讲中探讨了这个主题,事实证明,JDK本身在使用弃用时并不十分一致。它被用来指几个不同的东西,包括,例如,

  • 这是危险的,您应该意识到使用它的风险(例如:Thread.stop(),,,Thread.resume(),和Thread.suspend())
  • 这将在未来的版本中被删除。
  • 这是过时的,对您来说使用不同的东西是个好主意(例如:java.util.Date)

所有这些都是不同的含义,它们的不同子集适用于不同的被反对的事物。其中的一些子集适用于不受推荐的事物(但可能应该被废弃)。

CloneableObject.clone()都是“坏”的意思,因为它们有设计缺陷,很难正确使用。然而,clone()仍然是复制数组的最佳方法,而克隆对于复制精心实现的类的实例的用处有限。删除克隆将是一个不兼容的改变,将打破许多东西。克隆操作可以以不同的方式重新实现,但它可能比Object.clone().

然而,在大多数情况下,复制构造函数比克隆更可取。所以也许标记Cloneable因为“过时”或“取代”或类似的东西是合适的。这将告诉开发人员,他们可能想寻找其他地方,但这并不意味着克隆机制可能会在未来的版本中被删除。不幸的是,没有这样的标记。

就目前的情况来看,“弃用”似乎意味着最终会删除--尽管实际上已经删除了数量极少的弃用特性--因此,对克隆机制来说,不推荐似乎是没有必要的。也许在将来,可以使用替代标记来指导开发人员使用替代机制。

更新

jvm规范的共同作者,我在这里引用了相关的部分;完整的消息在bug报告中。

Cloneable没有任何方法,其原因与Serialable没有相同的原因。cloneable表示类的一个属性,而不是专门表示该类支持的方法。 在反射之前,我们需要一个本地方法来创建一个对象的浅拷贝。因此,Object.clon()就诞生了。很明显,许多类都希望重写此方法,而且并不是每个类都希望被克隆。因此,克隆人诞生是为了表明程序员的意图。 总之。cloneable的目的并不是表示您有一个公共的克隆()方法。它表明您愿意使用Object.Clonent()进行克隆,是否将克隆()公开取决于实现。

扫码关注云+社区