Cloneable

Cloneable

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);
    }
}

补充说明

  1. 代码细节提醒:原测试类中若使用浅拷贝(return super.clone();),修改 person2.m.money 后,person1.m.money 也会变为 99.9(引用共享);若使用深拷贝(当前代码),修改后 person1.m.money 仍为 9.9(引用独立)。
  2. 克隆核心步骤
    • 类实现 Cloneable 标记接口
    • 重写 Object 类的 protected Object clone() 方法
    • 调用 super.clone() 完成基础克隆,深拷贝需额外克隆引用类型成员
  3. 异常说明clone() 方法会抛出 CloneNotSupportedException,测试类中通过 main 方法声明抛出异常简化代码,实际开发中也可使用 try-catch 捕获处理。
重写部分Object方法 2025-07-10
String 2025-07-11

评论区