clone 的情况是独特的 并且相当反java - 首先不建议使用它是有原因的。 Cloneable 在 JDK 中的使用方式不是你应该注意的——这不是设计 API 的方式,Java 生态系统中没有其他任何东西可以这样工作。
奇怪的是,这很常见:java 的核心部分通常与 java 不同。例如,没有人会通过“它有一个带有签名public static void main(String[] args) 的方法来定义一个应用程序的API”。显而易见的设计原则是使用抽象 start() 方法创建一个抽象类或接口,并制作一个 java 应用程序,您编写一个具有无参数构造函数并实现/扩展该接口/类的类。数组也是如此:它们很奇怪——至少可以说,它们的 toString、equals 和 hashCode 实现令人惊讶。它们也不是完全类型安全的。
所有这一切的原因都是历史性的:要解释它们,您需要了解各种当时相关但不再重要且几十年来都不重要的事情。
可克隆也不例外。让我解释一下为什么会这样:
克隆的“系统”是JDK本身提供的,是普通库无法轻易实现的内置功能。有点像“java SomeClass 调用它的主要方法”是 java 本身的一部分。
但是,系统需要一种选择加入机制:克隆行为可能没有意义(“克隆”代表 TCP 网络连接的传入字节的 InputStream 是什么意思?“ clone' 试图保证只存在一个实例的枚举的值?“克隆”单例是什么意思?)
因此,“让所有对象都可克隆”是危险的,因此 java 不想这样做:他们希望您选择加入。 Java 希望类的作者明确地说:是的。我是可克隆的,使用标准机制(如果有记忆,可以深度复制所有字段)。
这就是Cloneable 的用途! - 这就是你说的如何:是的。我很好。通过实施。这是一面旗帜。
Java 也可以决定做类似的事情:
/** @cloneable */
public class Something {}
相反,但他们没有。如果它是在这个更现代的时代设计的,也许它看起来像:
@Cloneable
public class Something {}
但是在 java 1.5 中正确地引入了注释作为 1.6 中的演示功能。可克隆接口与 java 1.0 一样古老——十多年前。 “添加一个什么都不定义的接口”是当时标记类属性的标准方法,即使现在不是。
注意:您不只是 implements Cloneable,您还创建了一个公共克隆方法。 implements Cloneable 部分告诉克隆系统:您可以克隆此类,例如,即使它是正在克隆的包含对象的深层结构的一部分。创建一个调用j.l.Object 具有的受保护的JVM 提供的clone() 方法的克隆方法是公开API 的方式。也许您想将其命名为 copy,或者您希望克隆但不作为 public API 的一部分。你的问题不是关于如何使用克隆,而是它为什么会这样工作——如果你想使用它,我的建议很简单。不要,自己编写克隆代码,或者更好的是,用更多不可变对象设计您的 API,这样就不再需要克隆。