【Java SE】Clonable接口和深拷贝

目录

一.Clonable接口

实现步骤:

完整代码:

 二.深拷贝

实现步骤:

完整代码:

浅拷贝与深拷贝的对比

使用场景建议


 浅拷贝(Shallow Copy)和深拷贝(Deep Copy)是对象复制的两种方式,主要区别在于对对象内部引用类型字段的处理方式不同。

  • 浅拷贝:仅复制对象本身及其基本类型字段的值,对于引用类型字段,复制的是引用地址(即新对象和原对象共享同一块内存)。
  • 深拷贝:完全复制对象及其所有字段(包括引用类型字段),新对象与原对象不共享任何内存,彼此独立。

 一.Clonable接口

实现步骤:

①创建两个类

public class Test1 {
    public static void main(String[] args) {
        Person person1 = new Person(10,"zhangsan");
        //Person person2 = person1.clone();//最开始点不出来
    }
}
public class Person {
    public int age;
    public String name;

    public Person(int age, String name) {
        this.age = age;
        this.name = name;
    }

    @Override
    public String toString() {
        return "Person{" +
                "age=" + age +
                ", name='" + name + '\'' +
                '}';
    }
}

②通过 person1 调用 Object类 的 clone 方法 会失败

③重写 Object类 的 clone 方法

( Alt+Insert  → Generate → Override Methods → clone() )

④调用 重写 的 clone 方法 的返回值是Object类型,需要强转为(Person)

⑤现在运行会有一个异常

解决方法:

  • throws CloneNotSupportedException  ( 该内容在重写的clone()方法中 ) 
  • 复制到main方法的后面

⑥现在代码虽然不会报错,但是还会有异常(不支持克隆)

解决方法:在person类 后面加上一个接口(标记接口)


完整代码:

public class Person implements Cloneable {
    public int age;
    public String name;

    public Person(int age, String name) {
        this.age = age;
        this.name = name;
    }

    @Override
    public String toString() {
        return "Person{" +
                "age=" + age +
                ", name='" + name + '\'' +
                '}';
    }

    @Override
    protected Object clone()
            throws CloneNotSupportedException {
        return super.clone();
    }
}
public class Test1 {
    public static void main(String[] args)
            throws CloneNotSupportedException {
        Person person1 = new Person(10,"zhangsan");
        Person person2 = (Person) person1.clone();//最开始点不出来
    }
}


 二.深拷贝

实现步骤:

①创建一个类,包含 Clonable接口 和 clone() 方法

public class Money implements Cloneable{
    public double money = 9.9;

    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
}

并且在Person类中实例一个 Money对象 :m 

原理:

  • 通过改变 person2.m.money ,看 person1.m.money 是否被修改 
  • 如果改变 person2.m.money ,person1.m.money也被修改,那么就是浅拷贝,反之则为深拷贝

②再次重写Person类中的clone() 方法

    protected Object clone()
            throws CloneNotSupportedException {
        //return super.clone();
        Person tmp = (Person) super.clone();
        tmp.m = (Money) this.m.clone();
        return tmp;

    }

③进行调试

public class Test1 {
    public static void main(String[] args)
            throws CloneNotSupportedException {
        Person person1 = new Person(10,"zhangsan");
        Person person2 = (Person) person1.clone();//最开始点不出来
        System.out.println("修改前:"+person1.m.money);
        System.out.println("修改前:"+person2.m.money);
        person2.m.money = 99.99;
        System.out.println("修改后:"+person1.m.money);
        System.out.println("修改后:"+person2.m.money);
    }
}


完整代码:

public class Test1 {
    public static void main(String[] args)
            throws CloneNotSupportedException {
        Person person1 = new Person(10,"zhangsan");
        Person person2 = (Person) person1.clone();//最开始点不出来
        System.out.println("修改前:"+person1.m.money);
        System.out.println("修改前:"+person2.m.money);
        person2.m.money = 99.99;
        System.out.println("修改后:"+person1.m.money);
        System.out.println("修改后:"+person2.m.money);
    }
}
public class Person implements Cloneable {
    public int age;
    public String name;
    public Money m = new Money();
    public Person(int age, String name) {
        this.age = age;
        this.name = name;
    }

    @Override
    public String toString() {
        return "Person{" +
                "age=" + age +
                ", name='" + name + '\'' +
                '}';
    }

    @Override
    protected Object clone()
            throws CloneNotSupportedException {
        //return super.clone();
        Person tmp = (Person) super.clone();
        tmp.m = (Money) this.m.clone();
        return tmp;

    }
}
public class Money implements Cloneable{
    public double money = 9.9;

    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
}


浅拷贝与深拷贝的对比

特性浅拷贝深拷贝
复制范围仅复制对象本身和基本类型字段复制对象及其所有引用类型字段
内存占用低(共享引用类型字段)高(完全独立)
修改影响修改引用类型字段会影响原对象修改引用类型字段不影响原对象
实现复杂度简单复杂(需递归处理引用类型)

使用场景建议

  • 浅拷贝:适用于对象内部没有引用类型字段,或引用类型字段不可变(如String)。
  • 深拷贝:适用于对象内部有可变引用类型字段,且需要完全独立副本的场景(如缓存、状态快照等)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值