Object.clone() 设为 protected 是为强制子类显式声明克隆支持,避免盲目浅拷贝引发资源冲突;需实现 Cloneable、重写 public clone() 并手动处理深拷贝;推荐用构造器或静态工厂替代。

Object 类的 clone 方法是 protected 的,主要是为了强制子类主动选择是否支持克隆,并确保克隆行为被显式设计和控制,而不是被无意调用或误用。 它不是默认开放的 public 接口,因为浅拷贝语义不总是安全、合理或符合业务逻辑的——比如对象持有数据库连接、线程、文件句柄等不可复制资源时,盲目克隆会导致错误甚至崩溃。
为什么设计为 protected?
– 避免“自动可克隆”陷阱:如果 clone() 是 public,任何继承 Object 的类(即所有类)都“天然支持克隆”,但多数类并未准备处理字段复制、资源隔离或深拷贝逻辑。
– 强制契约声明:子类必须显式重写 clone() 并将访问权限改为 public(或包内可见),这相当于一种“我确认支持克隆”的信号。
– 与 Cloneable 接口协同工作:Cloneable 是个标记接口,本身无方法;仅当类实现它,Object.clone() 才会执行拷贝逻辑;否则抛 CloneNotSupportedException。protected 修饰符配合这个机制,把“是否可克隆”的决定权交给类的设计者,而非使用者。
正确重写 clone() 的关键步骤
– 实现 Cloneable 接口(否则 super.clone() 会直接抛异常)
– 重写 clone() 方法,声明为 public(否则外部无法调用)
– 调用 super.clone() 获取字段浅拷贝后的对象
– 对需要深拷贝的引用类型字段,手动克隆并赋值(如数组、集合、自定义对象等)
– 声明抛出 CloneNotSupportedException(可选,但建议保留,以保持与 Object.clone() 签名一致)
一个典型的安全重写示例
// 注意:仅适用于字段均为可克隆或不可变的情况
public class Person implements Cloneable {
private String name;
private int age;
private Address address; // 假设 Address 也实现了 Cloneable
@Override
public Person clone() {
try {
Person cloned = (Person) super.clone();
// 深拷贝引用字段
cloned.address = this.address != null ? this.address.clone() : null;
return cloned;
} catch (CloneNotSupportedException e) {
throw new AssertionError(e); // 不可能发生(已实现 Cloneable)
}
}
}
替代方案更推荐:优先使用构造器或静态工厂方法
– clone() 机制脆弱:依赖 Cloneable 标记、异常处理繁琐、深拷贝易遗漏、不支持 final 字段初始化
– 更清晰可控的方式:
• 提供带参数的构造器复制已有对象(如 new Person(other))
• 提供静态 copyOf() 方法(如 Person.copyOf(other))
• 使用现代序列化方式(如 Jackson、Records + builder)做深拷贝
这些方式语义明确、类型安全、IDE 友好,且不依赖运行时类型检查或特殊接口。


















