Kao*_*Kao 137 java deprecated cloneable java-8
通常理解CloneableJava 中的接口是破坏的.这有很多原因,我不会提及; 其他人已经做到了.它也是Java架构师自己的位置.
因此,我的问题是:为什么还没有被弃用?如果核心Java团队已经确定它已被破坏,那么他们也必须考虑弃用.他们这样做的原因是什么(在Java 8中,它仍然没有被弃用)?
Kao*_*Kao 119
有一个错误在1997年提交给Java的错误数据库有关添加clone()方法Cloneable,所以将不再是无用的.它以"不会修复"的决议结束,理由如下:
Sun的技术审查委员会(TRC)详细考虑了这个问题,并建议不要采取任何行动,而不是改进当前Cloneable接口的文档.以下是该建议的全文:
现有的Java对象克隆API存在问题.java.lang.Object上有一个受保护的"clone"方法,并且有一个接口java.lang.Cloneable.目的是如果一个类想要允许其他人克隆它,那么它应该支持Cloneable接口并使用公共克隆方法覆盖默认的受保护克隆方法.不幸的是,由于在时间迷雾中方便丢失的原因,Cloneable接口没有定义克隆方法.
这种组合导致了相当多的混乱.有些类声称支持Cloneable,但意外忘记支持克隆方法.开发人员对Cloneable应该如何工作以及克隆应该做什么感到困惑.
不幸的是,向Cloneable添加"克隆"方法将是一个不兼容的变化.它不会破坏二进制兼容性,但会破坏源兼容性.轶事证据表明,在实践中,有许多类支持Cloneable接口,但无法提供公共克隆方法.经过讨论,TRC一致建议我们不要修改现有的Cloneable接口,因为兼容性影响.
另一个建议是添加一个新接口java.lang.PubliclyCloneable以反映Cloneable的原始预期目的.以5比2多数,TRC建议不要这样做.主要担心的是,这会给已经混乱的图片增加更多的混淆(包括拼写错误!).
TRC一致建议我们应该在现有的Cloneable接口上添加其他文档,以更好地描述它的使用方式,并为实现者描述"最佳实践".
因此,虽然这不是直接关于弃用,但不使Cloneable"弃用"的原因是Technical Review Comitee决定修改现有文档足以使此接口有用.所以他们做到了.直到Java 1.4,Cloneable记录如下:
类实现了Cloneable接口,以向Object.clone()方法指示该方法合法地为该类的实例制作字段的字段副本.
尝试克隆未实现Cloneable接口的实例会导致抛出CloneNotSupportedException异常.
Cloneable接口声明没有方法.
从Java 1.4(2002年2月发布)到现在的版本(Java 8),它看起来像这样:
类实现了Cloneable接口,以向Object.clone()方法指示该方法合法地为该类的实例制作字段的字段副本.在未实现Cloneable接口的实例上调用Object的clone方法会导致抛出异常CloneNotSupportedException.
按照惯例,实现此接口的类应使用公共方法覆盖Object.clone(受保护).有关重写此方法的详细信息,请参阅Object.clone().
请注意,此接口不包含克隆方法.因此,仅仅通过实现该接口的事实来克隆对象是不可能的.即使反射调用clone方法,也无法保证它会成功.
Stu*_*rks 63
对"为什么不Cloneable被弃用?" 的简短回答.(或者,实际上,为什么不X被弃用,对于任何X)是因为没有太多关注它们.
最近弃用的大多数内容都已弃用,因为有一个特定的计划要删除它们.例如,在Java SE 8中不推荐使用LogManageraddPropertyChangeListener和removePropertyChangeListener方法,目的是在Java SE 9中删除它们.(原因是它们不必要地复杂了模块的相互依赖性.)实际上,这些API已经从早期的JDK 9开发中删除了建立.(请注意,类似的属性更改侦听器调用也已从中删除;请参阅JDK-8029806.)Pack200
没有这样类似的计划存在为Cloneable和Object.clone().
更长的答案将涉及讨论进一步的问题,例如人们可能期望在这些API上发生的事情,如果平台被弃用会产生什么样的成本或收益,以及在API被弃用时与开发人员沟通的内容.我在最近的JavaOne谈话,债务和弃权中探讨了这个话题.(该链接提供幻灯片; 此处为视频.)事实证明,JDK本身在使用弃用方面并不十分一致.它被用来表示几种不同的东西,包括例如,
这是危险的,你应该知道使用它的风险(例如:Thread.stop(),Thread.resume(),和Thread.suspend()).
这将在未来的版本中删除
java.util.Date)所有这些都是不同的含义,它们的不同子集适用于不同的不赞成的东西.其中一些子集适用于未弃用的内容(但可能应该弃用).
Cloneable并且Object.clone()在它们具有设计缺陷并且难以正确使用的意义上被"破坏".但是,clone()仍然是复制数组的最佳方法,克隆对于精心实现的类实例的副本有一些有限的用处.删除克隆将是一个不兼容的变化,会破坏很多东西.克隆操作可以以不同的方式重新实现,但它可能会慢于Object.clone().
但是,对于大多数情况,复制构造函数优于克隆.因此,标记Cloneable为"过时"或"取代"或类似的东西也是合适的.这将告诉开发人员他们可能想要寻找其他地方,但它并不表示在将来的版本中可能会删除克隆机制.不幸的是,不存在这样的标记.
事实上,"弃用"似乎意味着最终被删除 - 尽管事实上已经删除了少量被弃用的功能 - 因此克隆机制似乎不需要弃用.也许将来可以应用替代标记,指导开发人员使用替代机制.
UPDATE
我在错误报告中添加了一些额外的历史记录.早期的JVM实现者和JVM规范的共同作者Frank Yellin在另一个答案引用的TRC建议中回应了"迷失在时间之中"的评论.我在这里引用了相关部分; 完整的消息在错误报告中.
Cloneable没有方法与Serializable没有相同的原因.Cloneable表示类的属性,而不是具体说明该类支持的方法.
在反射之前,我们需要一个本机方法来制作一个Object的浅表副本.因此,Object.clone()诞生了.很明显,许多类都希望覆盖此方法,并不是每个类都希望被克隆.因此Cloneable的诞生是为了表明程序员的意图.
所以,简而言之.Cloneable的目的不是表明你有一个公共clone()方法.这表明你愿意使用Object.clone()进行克隆,并且由实现决定是否公开clone().
| 归档时间: |
|
| 查看次数: |
8620 次 |
| 最近记录: |