首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >为什么Cloneable没有被弃用?

为什么Cloneable没有被弃用?
EN

Stack Overflow用户
提问于 2014-10-16 15:48:42
回答 3查看 9.6K关注 0票数 142

人们通常认为Java中的Cloneable接口是坏的。这样做的原因有很多,我不会提及;others已经做到了。这也是Java architects本身的立场。

因此,我的问题是:为什么还没有被弃用?如果核心Java团队认为它已经坏了,那么他们一定也考虑过弃用。他们反对这样做的理由是什么(在Java8中是still not deprecated)?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2014-10-16 19:31:07

1997年向Java Bug Database提交了一份关于将clone()方法添加到Cloneablebug,因此它不再是无用的。它是以“with‘t fix”解决方案关闭的,理由如下:

太阳公司的技术审查委员会详细考虑了这个问题,并建议除了改进当前可克隆接口的文档之外,不要采取任何行动。以下是该建议的全文:

现有的Java对象克隆API存在问题。在java.lang.Object上有一个受保护的“克隆”方法,并且有一个接口java.lang.Cloneable。其意图是,如果一个类想要允许其他人克隆它,那么它应该支持Cloneable接口,并用一个公共的clone方法覆盖默认的受保护的clone方法。不幸的是,由于时间的原因,Cloneable接口并没有定义clone方法。

这种组合导致了相当大的混乱。一些类声称支持Cloneable,但却意外忘记了支持clone方法。开发人员对Cloneable应该如何工作以及克隆应该做什么感到困惑。

不幸的是,向Cloneable添加"clone“方法将是一个不兼容的更改。它不会破坏二进制兼容性,但会破坏源代码兼容性。轶事证据表明,在实践中,有许多情况下,类支持Cloneable接口,但未能提供公共克隆方法。经过讨论,TRC一致建议我们不应该修改现有的可克隆接口,因为这会影响兼容性。

另一个建议是添加一个新的接口java.lang.PubliclyCloneable,以反映Cloneable最初的预期目的。以5比2的多数,TRC建议反对这一点。主要的担心是这会增加更多的混乱(包括拼写混乱!)一幅本已混乱的图景。

TRC一致建议我们应该向现有的可克隆接口添加额外的文档,以便更好地描述如何使用它,并为实现者描述“最佳实践”。

因此,尽管这不是直接关于弃用的,但不使可克隆的“弃用”的原因是技术审查委员会认为,修改现有文档的将足以使该接口有用的。他们就是这么做的。在Java1.4之前,Cloneable的文档如下所示:

Cloneable类实现Cloneable接口,以向Object.clone()方法指示该方法对该类的实例进行字段对字段复制是合法的。

尝试克隆未实现Cloneable接口的实例会导致抛出异常CloneNotSupportedException。

Cloneable接口没有声明任何方法。

从Java1.4(2002年2月发布)到当前版本(Java8),它看起来是这样的:

Cloneable类实现Cloneable接口,以向Object.clone()方法指示该方法对该类的实例进行字段对字段复制是合法的。在没有实现Cloneable接口的实例上调用对象的克隆方法会导致抛出异常CloneNotSupportedException。

按照约定,实现此接口的类应使用公共方法重写Object.clone (受保护的)。有关覆盖此方法的详细信息,请参阅Object.clone()。

请注意,此接口不包含clone方法。因此,仅仅因为对象实现了该接口,就不可能克隆该对象。即使以反射方式调用克隆方法,也不能保证它会成功。

票数 121
EN

Stack Overflow用户

发布于 2014-10-17 07:30:52

简短的回答是“为什么Cloneable不被弃用?”(或者实际上,对于任何X,为什么X没有被弃用)是因为人们没有太多地关注对它们的弃用。

大多数最近被弃用的东西都被弃用了,因为有一个具体的计划来删除它们。例如,LogManageraddPropertyChangeListenerremovePropertyChangeListener方法是deprecated in Java SE 8,目的是在JavaSE9中删除它们(原因是它们不必要地使模块相互依赖关系变得复杂)。实际上,这些API已经成为removed from early JDK 9开发版本。(请注意,类似的属性更改侦听器调用也已从Pack200中删除;请参阅JDK-8029806。)

对于CloneableObject.clone(),没有类似的计划。

更长的答案将涉及讨论进一步的问题,例如,人们可能会期望这些API发生什么,如果它们被弃用,平台将产生什么成本或好处,以及当API被弃用时,将向开发人员传达什么。我在最近的JavaOne演讲Debt and Deprecation中探讨了这个话题。(可通过该链接查看幻灯片;video here。)事实证明,JDK本身在使用弃用方面并不是非常一致。它已经被用来表示几种不同的东西,例如,

这很危险,您应该意识到使用它的风险(例如:Thread.stop()Thread.resume()

  • Thread.stop()

  • 这将在未来版本的

中删除

这已经过时了,最好使用一些不同的方法(例如:java.util.Date)中的许多

所有这些都是不同的含义,并且它们的不同子集适用于不推荐使用的不同事物。它们中的一些子集适用于没有被弃用的东西(但可能应该被弃用)。

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

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

在目前的情况下,“弃用”似乎意味着最终的删除--尽管有一小部分被弃用的特性曾经被删除过--因此,对于克隆机制来说,弃用似乎是不必要的。也许在未来,可以应用另一种标记,指导开发人员使用替代机制。

更新

我已经在bug report中添加了一些额外的历史记录。Frank Yellin是一位早期的JVM实现者,也是JVM规范的合著者,他对other answer引用的TRC建议中的“迷失在时间的迷雾中”的评论做了一些评论。我在这里引用了相关部分;完整的消息在bug报告中。

Cloneable没有方法的原因与Serializable没有相同的原因。Cloneable表示类的属性,而不是专门说明类支持的方法。

在反射之前,我们需要一个本机方法来制作对象的浅层副本。因此,Object.clone()诞生了。很明显,许多类都想要覆盖这个方法,而且并不是每个类都想被克隆。因此Cloneable的诞生表明了程序员的意图。

所以,简而言之。Cloneable的目的并不是表明您有一个公共的clone()方法。它表明您愿意使用Object.clone()进行克隆,并且由实现决定是否将clone()设置为公共的。

票数 64
EN

Stack Overflow用户

发布于 2014-10-16 16:49:53

为什么它还没有被弃用?

因为JCP认为不适合这样做,而且可能永远不会这样做。问问他们。你问错地方了。

将其保留在Java API中的原因是什么

没有人会从Java API中删除任何东西,因为需要向后兼容。上一次发生这种情况是在1996/7年,AWT事件模型在1.0和1.1之间进行了更改。

票数 -2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/26398951

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档