深克隆与浅克隆详细区别

本文详细介绍了Java中的对象克隆,包括Object类中的clone方法、浅克隆和深克隆的概念。通过实例展示了如何实现浅克隆和深克隆,解释了两者在处理引用对象时的区别。浅克隆只会复制对象的基本类型和String属性,而引用类型的属性仍然是共享的。深克隆则会递归复制所有属性,包括引用类型,确保克隆对象和原对象完全独立。
摘要由CSDN通过智能技术生成

对象克隆

Object类中定义了一个clone方法

protected native Object() throws cloneNotSupportedException;
//native方法用于声明一个非java语言实现的代码,供java程序调用
//因为java语言程序是运行在JVM上的,如果要访问底层与操作系统相关的方式就没有办法了
//只能通过如C语言高进系统的语言来实现

浅克隆

  • 被赋值的类需要实现Cloneable接口,该接口也是旗标接口,不包含任何方法
  • 在当前类中覆盖clone方法,将访问限定词设置为public。具体实现则是通过调用super.clone()实现的

主类Person
Person类中包含值属性和对象属性

public class Person implements Cloneable {
    private long id;
    private Student stu;

    public long getId() {
        return id;
    }

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

    public Student getStu() {
        return stu;
    }

    public void setStu(Student stu) {
        this.stu = stu;
    }

    @Override
    public String toString() {
        return "Person{" + "id=" + id + ", stu=" + stu + '}';
    }

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

引用对象类Student

public class Student {
    private String name;

    public String getName() {
        return name;
    }

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

    @Override
    public String toString() {
        return "Student{" + "name='" + name + '}';
    }
}

浅克隆测试类Test

public class Test{
	public static void main(String[] args) throws CloneNotSupportedException {
        Person pClone = (Person)person.clone();//进行克隆对象
        System.out.println("修改前pClone:"+pClone);
        System.out.println("修改前person:"+person);
        pClone.setId(2);
        System.out.println("修改值引用后的pClone:"+pClone);
        System.out.println("修改值引用后的person:"+person);
        stu.setName("Hanmeimei");
        person.setStu(stu);
        System.out.println("修改对象引用后的pClone:"+pClone);
        System.out.println("修改对象引用后的person:"+person);
    }
}
//修改前pClone:Person{id=1, stu=Student{name='Liming'}}
//修改前person:Person{id=1, stu=Student{name='Liming'}}
//修改值引用后的pClone:Person{id=2, stu=Student{name='Liming'}}
//修改值引用后的person:Person{id=1, stu=Student{name='Liming'}}
//修改对象引用后的pClone:Person{id=2, stu=Student{name='Hanmeimei'}}
//修改对象引用后的person:Person{id=1, stu=Student{name='Hanmeimei'}}
//显而易见,修改对象引用中对象的属性,两个Person对象中的stu对象引用都进行了变化

浅克隆只会克隆引用类型属性的地址,并不是克隆引用类型属性。将会出现源对象和克隆对象的属性指向同一个对象属性。在浅克隆中当对象被复制时,他本身和其中包含的值类型的成员属性,而引用类型的成员对象并没有复制。

深克隆

在深克隆中无论原型对象的成员变量是值类型还是应用类型,都将复制一份给克隆对象
在java中实现深克隆有两种方案:

  • 可以覆盖Object的clone方法实现
  • 也可以通过实现序列化来实现

主类Person

public class Person implements Cloneable, Serializable {
    private static final long serialVersionUID = 1L;
    private long id;
    private Student stu;

    public long getId() {
        return id;
    }

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

    public Student getStu() {
        return stu;
    }

    public void setStu(Student stu) {
        this.stu = stu;
    }

    @Override
    public String toString() {
        return "Person{" + "id=" + id + ", stu=" + stu + '}';
    }

    @Override
    protected Object clone() throws CloneNotSupportedException {
        try {
            //序列化
            ByteArrayOutputStream bos = new ByteArrayOutputStream();
            ObjectOutputStream oos = new ObjectOutputStream(bos);
            //写入到当前类(也可以写入到文件)
            oos.writeObject(this);
            //反序列化
            ByteArrayInputStream bais = new ByteArrayInputStream(bos.toByteArray());
            ObjectInputStream ois = new ObjectInputStream(bais);
            return (Object) ois.readObject();
        } catch (Exception e) {
            e.printStackTrace();
            System.out.println("克隆出错"+e.getStackTrace());
            return null;
        }
    }
}

引用对象类Student

public class Student implements Cloneable, Serializable {
    private static final long serialVersionUID = 1L;
    private String name;

    public String getName() {
        return name;
    }

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

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

    @Override
    public String toString() {
        return "Student{" + "name='" + name + '}';
    }
}

深克隆测试类Test

public class Test{
	public static void main(String[] args) throws CloneNotSupportedException {
        Person person = new Person();//创建一个Person对象
        Student stu = new Student();//创建Person中的引用对象
        person.setId(1);
        stu.setName("Liming");
        person.setStu(stu);

        Person pClone = (Person)person.clone();//进行克隆对象
        System.out.println("修改前pClone:"+pClone);
        System.out.println("修改前person:"+person);
        pClone.setId(2);
        System.out.println("修改值引用后的pClone:"+pClone);
        System.out.println("修改值引用后的person:"+person);
        stu.setName("Hanmeimei");
        person.setStu(stu);
        System.out.println("修改对象引用后的pClone:"+pClone);
        System.out.println("修改对象引用后的person:"+person);
    }
}
//修改前pClone:Person{id=1, stu=Student{name='Liming'}}
//修改前person:Person{id=1, stu=Student{name='Liming'}}
//修改值引用后的pClone:Person{id=2, stu=Student{name='Liming'}}
//修改值引用后的person:Person{id=1, stu=Student{name='Liming'}}
//修改对象引用后的pClone:Person{id=2, stu=Student{name='Liming'}}
//修改对象引用后的person:Person{id=1, stu=Student{name='Hanmeimei'}}
//显而易见,修改了原类的引用对象的属性时(由stu.setName('LIMing')修改为'Hanmeimei'),克隆类对象的引用对象的属性并未发生变化依旧是

深克隆和浅克隆的区别

  1. 深克隆:对当前对象进行克隆,并克隆该对象所包含的8中基本数据类型和String类型属性(拷贝一份该对象并重新分配内存,即产生了新的对象);但如果被克隆的对象中包含除8中数据类型和String类型外的其他类型的属性,浅克隆并不会克隆这些属性(即不会为这些属性分配内存,而是引用原来对象中的属性)。
  2. 深克隆:深克隆是在浅克隆的基础上,递归地克隆除8种基本数据类型和String类型外的属性(即为这些属性重新分配内存而非引用原来对象中的属性)
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值