Java 中通过实现 Cloneable 接口、重写 Object 类的 clone() 方法,可实现对象的克隆,本次同时演示浅拷贝和深拷贝两种方式,核心区别在于是否克隆引用类型成员变量。
说明:
Cloneable是一个标记接口(无任何抽象方法),仅用于标记该类允许被克隆,若未实现该接口直接调用clone()方法,会抛出CloneNotSupportedException异常。
1. 定义 Money 类(引用类型,用于演示深拷贝)
public class Money implements Cloneable { // 实现 Cloneable 接口,允许该类对象被克隆
public double money = 9.9;
// 重写 Object 类的 clone() 方法,支持 Money 对象自身的克隆
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
2. 定义 Person 类(实现 Cloneable 接口,实现浅拷贝 & 深拷贝)
// 实现 Cloneable 标记接口,表明该类对象可以被克隆
public class Person implements Cloneable {
public int id; // 基本数据类型成员变量
public Money m = new Money(); // 引用数据类型成员变量(Money 类对象)
// 构造方法:初始化 id
public Person(int id) {
this.id = id;
}
// 重写 toString() 方法:自定义 Person 对象打印格式
@Override
public String toString() {
return "Person{" +
"id=" + id +
'}';
}
// 重写 Object 类的 clone() 方法,实现对象克隆(此处为深拷贝,注释中包含浅拷贝实现)
@Override
protected Object clone() throws CloneNotSupportedException {
// ------------ 浅拷贝:仅克隆当前对象,引用类型成员变量仍指向原对象地址 ------------
// return super.clone();
// ------------ 深拷贝:克隆当前对象 + 克隆所有引用类型成员变量 ------------
// 1. 先对 Person 对象进行浅拷贝,得到临时对象 tmp
Person tmp = (Person) super.clone();
// 2. 对 Person 中的引用类型成员变量 m(Money 对象)进行克隆,避免引用共享
tmp.m = (Money) this.m.clone();
// 3. 返回深拷贝后的完整对象
return tmp;
}
}
3. 测试类(验证对象克隆功能)
public class Test {
// main 方法声明抛出 CloneNotSupportedException 异常(简化代码,避免 try-catch 包裹)
public static void main(String[] args) throws CloneNotSupportedException {
// 1. 创建原始 Person 对象
Person person1 = new Person(1);
// 2. 调用 clone() 方法克隆对象,需进行强制类型转换(返回值为 Object 类型)
Person person2 = (Person) person1.clone();
// 3. 打印克隆前后两个对象的 Money 成员变量值
System.out.println("克隆前 - person1 金钱值:" + person1.m.money);
System.out.println("克隆后 - person2 金钱值:" + person2.m.money);
System.out.println("====================");
// 4. 修改克隆对象 person2 的 Money 成员变量值
person2.m.money = 99.9;
// 5. 再次打印两个对象的 Money 成员变量值,验证深拷贝效果
System.out.println("修改后 - person1 金钱值:" + person1.m.money);
System.out.println("修改后 - person2 金钱值:" + person2.m.money);
}
}
补充说明
- 代码细节提醒:原测试类中若使用浅拷贝(
return super.clone();),修改person2.m.money后,person1.m.money也会变为99.9(引用共享);若使用深拷贝(当前代码),修改后person1.m.money仍为9.9(引用独立)。 - 克隆核心步骤:
- 类实现
Cloneable标记接口 - 重写
Object类的protected Object clone()方法 - 调用
super.clone()完成基础克隆,深拷贝需额外克隆引用类型成员
- 类实现
- 异常说明:
clone()方法会抛出CloneNotSupportedException,测试类中通过main方法声明抛出异常简化代码,实际开发中也可使用try-catch捕获处理。