Java中实现浅拷贝需类实现Cloneable接口并重写public clone()方法,否则抛CloneNotSupportedException;Object.clone()执行字段级逐位复制,引用类型共享对象,深拷贝需手动处理。

Java 中使用 Object.clone() 实现浅拷贝,需要类实现 Cloneable 接口并重写 clone() 方法。否则会抛出 CloneNotSupportedException。
必须实现 Cloneable 接口
Cloneable 是一个空的标记接口,不包含任何方法。它的作用是告诉 JVM:当前类允许被克隆。如果不实现该接口就调用 clone(),运行时会抛出异常。
示例:
public class Person implements Cloneable {
private String name;
private int age;
private Address address; // 假设 Address 是另一个类
// 构造、getter、setter 省略
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone(); // 调用 Object 的 clone 方法
}
}
clone() 方法必须声明为 public 并处理异常
Object.clone() 是 protected 的,且声明抛出 CloneNotSupportedException。子类重写时通常改为 public,并选择捕获或声明该异常。
立即学习“Java免费学习笔记(深入)”;
推荐写法(声明异常):
@Override
public Object clone() throws CloneNotSupportedException {
return super.clone();
}
或更类型安全的写法(返回具体类型):
@Override
public Person clone() throws CloneNotSupportedException {
return (Person) super.clone();
}
浅拷贝的特点与注意事项
默认的 super.clone() 执行的是**字段级逐位复制**(bitwise copy),对基本类型和不可变对象(如 String)没问题;但对引用类型,只复制引用地址,新旧对象共享同一堆内存中的对象。
这意味着:
- 修改原始对象的
name或age,不会影响克隆对象; - 但修改原始对象的
address.city,克隆对象的address.city也会变(因为它们指向同一个Address实例)。
若需避免这种共享,需在 clone() 方法中手动深拷贝引用字段(例如:this.address = (Address) address.clone();,前提是 Address 也支持克隆)。
调用 clone 时记得处理异常
由于 clone() 声明抛出受检异常,调用处必须用 try-catch 或向上抛出:
try {
Person copy = original.clone();
} catch (CloneNotSupportedException e) {
// 处理异常,例如记录日志或抛运行时异常
throw new RuntimeException(e);
}
注意:JVM 保证 Cloneable 类的 clone() 不会真的抛出该异常,所以 catch 块通常用于兜底或转换异常类型。


















