java中浅拷贝的核心是实现cloneable接口并重写public clone()方法,调用super.clone();其默认行为为浅拷贝,即基本类型字段独立复制,引用类型字段仅复制引用地址,新旧对象共享同一堆内存中的子对象。

Java 中用 clone() 实现对象浅拷贝,核心是让类实现 Cloneable 接口并重写 clone() 方法。默认的 Object.clone() 就是浅拷贝——它只复制对象本身字段的值,对引用类型字段,仅复制引用(即新旧对象共享同一堆内存中的子对象)。
1. 基础步骤:实现 Cloneable 并重写 clone()
必须显式实现 Cloneable 接口(空标记接口),否则调用 clone() 会抛 CloneNotSupportedException。重写时建议声明为 public,并用 super.clone() 调用父类实现:
- 声明类实现
Cloneable - 重写
clone()方法,调用super.clone() - 处理受检异常(通常直接抛出或包装为运行时异常)
示例:
public class Person implements Cloneable {
private String name;
private int age;
private Address address; // 引用类型
public Person(String name, int age, Address address) {
this.name = name;
this.age = age;
this.address = address;
}
@Override
public Person clone() {
try {
return (Person) super.clone();
} catch (CloneNotSupportedException e) {
throw new RuntimeException(e);
}
}
}
2. 浅拷贝的关键表现:基本类型独立,引用类型共享
执行 Person p2 = p1.clone(); 后:
-
p1.name和p2.name是两个独立字符串(String 不可变,实际效果等价于深拷贝) -
p1.age和p2.age是独立的 int 值 -
p1.address和p2.address指向同一个Address对象
因此修改 p2.getAddress().setCity("Shanghai"),p1.getAddress().getCity() 也会变成 "Shanghai"。
3. 注意事项与常见陷阱
-
Cloneable不含clone()方法,纯属标记——不实现它,super.clone()会直接抛异常 -
Object.clone()是protected的,子类需重写为public才能外部调用 - 数组类型字段(如
int[]、String[])调用clone()也是浅拷贝:新数组和原数组内容相同,但元素仍共享(对对象数组而言) - 若类有 final 字段,且类型不可变(如
String,Integer),不影响浅拷贝;但若 final 字段是可变对象(如final List<string></string>),其内部状态仍会被共享
4. 什么时候该用浅拷贝?
适合以下场景:
- 对象结构简单,不含可变引用类型字段
- 引用字段本身不可变(如
String,LocalDateTime) - 明确希望新对象与原对象共享某些底层数据(比如共用配置、缓存、连接池句柄)
- 性能敏感,且能接受引用共享带来的副作用
若需要完全隔离副本,应改用深拷贝(手动复制、序列化、或使用第三方库如 Apache Commons Lang 的 SerializationUtils.clone())。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











