1997 年向 Java Bug 数据库提交了一个关于添加方法的错误,所以它不再是无用的。它以决议“不会修复”结束,理由如下:clone()
Cloneable
Sun的技术审查委员会(TRC)详细考虑了这个问题,并建议除了改进当前可克隆接口的文档之外,不要采取任何行动。以下是建议的全文:
现有的 Java 对象克隆 API 存在问题。java.lang.Object上有一个受保护的“clone”方法,还有一个java.lang.Cloneable接口。其目的是,如果一个类想要允许其他人克隆它,那么它应该支持 Cloneable 接口,并使用公共克隆方法覆盖默认的受保护克隆方法。不幸的是,由于容易迷失在时间迷雾中的原因,Cloneable接口没有定义克隆方法。
这种组合会导致相当多的混乱。某些类声称支持 Cloneable,但意外忘记了支持 clone 方法。开发人员对 Cloneable 应该如何工作以及 clone 应该做什么感到困惑。
不幸的是,向 Cloneable 添加“clone”方法将是一个不兼容的更改。它不会破坏二进制兼容性,但会破坏源代码兼容性。轶事证据表明,在实践中,有许多情况下,类支持可克隆接口,但未能提供公共克隆方法。经过讨论,TRC一致建议我们不要修改现有的可克隆接口,因为兼容性影响。
另一个建议是添加一个新的接口java.lang.PubliclyCloneable,以反映Cloneable的原始预期目的。TRC以5比2的多数建议反对。主要担心的是,这会给已经混乱的图片增加更多的混乱(包括拼写混乱!)。
TRC一致建议,我们应该向现有的可克隆接口添加其他文档,以更好地描述它的使用方式,并为实现者描述“最佳实践”。
因此,尽管这与弃用并不直接相关,但未使Cloneable“弃用”的原因是Technical Review Comitee认为修改现有文档足以使此接口有用。所以他们做到了。在Java 1.4之前,有如下文档记录:Cloneable
类实现 Cloneable 接口,以向 Object.clone() 方法指示该方法对该类的实例进行逐字段复制是合法的。
尝试克隆未实现可克隆接口的实例会导致引发异常 CloneNotSupportedException。
可克隆接口不声明任何方法。
从Java 1.4(于2002年2月发布)到当前版本(Java 8),它看起来像这样:
类实现 Cloneable 接口,以向 Object.clone() 方法指示该方法对该类的实例进行字段对字段复制是合法的。在未实现 Cloneable 接口的实例上调用 Object 的 clone 方法会导致引发异常 CloneNotSupportedException。
按照约定,实现此接口的类应使用公共方法重写 Object.clone(受保护)。有关重写此方法的详细信息,请参阅 Object.clone()。
请注意,此接口不包含克隆方法。因此,仅凭它实现此接口这一事实就不可能克隆对象。即使以反射方式调用了 clone 方法,也不能保证它会成功。
对“为什么没有被弃用?(或者实际上,为什么不被弃用,对于任何)是没有太多的注意力来弃用它们。Cloneable
X
X
最近已弃用的大多数内容都被弃用,因为有一个特定的计划来删除它们。例如,LogManager 的和方法在 Java SE 8 中被弃用,目的是在 Java SE 9 中删除它们。(原因是它们不必要地使模块相互依赖性复杂化。事实上,这些 API 已经从早期的 JDK 9 开发版本中移除了。(请注意,类似的属性更改侦听器调用也已从中删除;请参阅 JDK-8029806。addPropertyChangeListener
removePropertyChangeListener
Pack200
不存在与 for 和 类似的计划。Cloneable
Object.clone()
更长的答案将涉及讨论进一步的问题,例如人们可能期望这些API发生什么,如果它们被弃用,平台将产生什么成本或收益,以及当API被弃用时,将传达给开发人员什么。我在最近的JavaOne演讲《债务和弃用》中探讨了这个话题。(该链接提供幻灯片;视频在这里。事实证明,JDK本身在弃用方面的使用并不是很一致。它被用来表示几种不同的东西,包括例如,
-
这是危险的,您应该了解使用它的风险(例如:,和)。
Thread.stop()
Thread.resume()
Thread.suspend()
-
这将在将来的版本中被删除
-
这已经过时了,最好使用不同的东西(例如:中的许多方法
java.util.Date
)
所有这些都是不同的含义,它们的不同子集适用于已弃用的不同内容。其中一些子集适用于未弃用的内容(但可能应该被弃用)。
Cloneable
并且“破碎”,因为它们具有设计缺陷并且难以正确使用。但是,仍然是复制数组的最佳方法,并且克隆对于制作精心实现的类的实例的副本具有一些有限的用处。删除克隆将是一个不兼容的更改,会破坏很多东西。克隆操作可以以不同的方式重新实现,但它可能比 慢。Object.clone()
clone()
Object.clone()
但是,对于大多数事情,复制构造函数比克隆更可取。因此,也许标记为“过时”或“被取代”或类似的东西是合适的。这将告诉开发人员他们可能想在其他地方寻找,但它不会表明克隆机制可能会在将来的版本中被删除。不幸的是,不存在这样的标记。Cloneable
就目前而言,“弃用”似乎意味着最终的删除 - 尽管事实上只有极少数已弃用的功能已被删除 - 因此弃用似乎没有理由用于克隆机制。也许将来可以应用一种替代标记,指导开发人员使用替代机制。
更新
我已经向错误报告添加了一些额外的历史记录。早期的JVM实现者和JVM规范的合著者Frank Yellin对另一个答案中引用的TRC建议中“迷失在时间迷雾中”的评论做出了一些评论。我在这里引用了相关部分;完整的消息在错误报告中。
Cloneable没有方法,原因与Sscribializable没有的原因相同。Cloneable 指示类的属性,而不是专门说明该类支持的方法。
在反射之前,我们需要一个本机方法来制作对象的浅层副本。因此Object.clone()诞生了。同样清楚的是,许多类都希望重写此方法,并且并非每个类都希望被克隆。因此,Cloneable的诞生是为了表明程序员的意图。
所以,简而言之。Cloneable 的目的不是表明您有一个公共 clone() 方法。这是为了表明你愿意使用 Object.clone() 进行克隆,并且由实现来决定是否公开 clone()。
-
如何使用Java中的RESTful Web服务获取远程/客户端IP地址? 我已经在我的项目中编写了Rest Web服务。Web服务调用可能来自不同 machine.so 我需要通过REST Web服务找出IP地址。 从这个请求.getRemoteAddr()使用这个。 但是我不能使用getRemoteAddr()。因为我的请
-
从包含大量文件的zip文件中提取1文件的最快方法是什么? 我尝试了但它们也缺少一些东西。 LZMA SDK不提供一种如何使用的文档/教程,这非常令人沮丧。没有 javadoc。 虽然7z jbinding没有提供一种简单的方法来只提取1个文件,但是,它只提供了提取zip文件
-
输入/输出流在销毁时是否关闭? Java 中的 InputStreams 和 OutputStreams 是否在销毁时关闭()?我完全理解这可能是不好的形式(特别是在C和C++世界中),但我很好奇。 另外,假设我有以下代码: 无名的FileInputStream是否在p.load
-
Java 程序中的字符串大小是否有任何限制? 我有一个字符串定义为 字符串 xx 我可以分配的字符数是否有任何限制? 2) 我正在将用户输入分配给此字符串 xx。70%的人只说一个字。有时他们给出一个大句子,所以想知道可
-