Java的浅度克隆和深度克隆

本文详细解析了Java中对象克隆的基本原理,包括浅度克隆与深度克隆的区别,并通过具体实例展示了如何实现对象的深度克隆。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

前言:

protected native Object clone() throws CloneNotSupportedException

方法由protected修饰,只能由子类重写和调用,而且为本地方法。

Object提供clone方法,生成对象的一个副本,来实现对象的一次浅度克隆。但是对象的引用类型不会拷贝一份,引用地址与原对象相同。

实现对象的克隆需要实现Cloneable接口,重写clone方法,通过super.clone()调用Object类的clone方法得到当前对象的副本,并放回该副本。


浅度克隆与深度克隆的区别:

浅度克隆:基本类型都会拷贝一份,引用类型引用地址不变,还是同一个对象。

深度克隆:基本类型和引用类型都会拷贝一份,完完全全的是不同的两份,引用地址不一样。


下面结合一个具体的例子:(两者结合)

定义person类:(实现了Cloneable接口)

class Person implements Cloneable{
    int id;

    public Person(int id) {
        this.id = id;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
}
定义Student类(实现Cloneable接口)

public class Student implements Cloneable{
    private int age;  //基本类型
    private String name;  //引用类型,未实现自己的深度拷贝
    private Person person;  //引用类型,Person类实现了Cloneable接口,深度拷贝

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

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Person getPerson() {
        return person;
    }

    public void setPerson(Person person) {
        this.person = person;
    }

    @Override
    protected Object clone() throws CloneNotSupportedException {
        Student student = (Student) super.clone();  
        Person person = (Person) student.getPerson().clone();  //这个为重点,把student里面的引用类型person深度克隆
        student.setPerson(person);
        return student;
    }

    public static void main(String[] args) throws Exception{
        Person person = new Person(2);
        Student student1 = new Student(10,"wqh", person);
        Student student2 = (Student) student1.clone();
        System.out.println(student1 == student2);  //false
        System.out.println(student1.getName()==student2.getName()); //true
        System.out.println(student1.getPerson() == student2.getPerson());  //false
    }
}

输出结果:
false
true
false

分析:

Student中有两个引用类型:String和Person,在Person中实现了clone接口,在Student的clone方法中我们对person属性也进行了一次深度克隆,这样对student1拷贝成student2后,各自的person属性是单独的两份,引用地址不一样,所以为false,但是string属性是同一份,故为true。综述,对student2而言,这是一次不彻底的深度克隆,因为部分引用属性没有进行深度克隆。

画个图来明了下:


student1和student2对应于堆中的同一个name,不同的person。



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值