JAVA中浅克隆和深克隆

1 浅克隆和深克隆的区别

1、浅克隆:对当前对象进行克隆,并克隆该对象所包含的8种基本数据类型和String类型属性(拷贝一份该对象并重新分配内存,即产生了新的对象);但如果被克隆的对象中包含除8中数据类型和String类型外的其他类型的属性,浅克隆并不会克隆这些属性(即不会为这些属性分配内存,而是引用原来对象中的属性)。


2、深克隆:深克隆是在浅克隆的基础上,递归地克隆除8种基本数据类型和String类型外的属性(即为这些属性重新分配内存而非引用原来对象中的属性)

2 浅克隆与深克隆的特点

1、被克隆的对象的类应实现 Cloneable 接口,并重写 clone() 方法
2、浅克隆中由于除8中数据类型和String类型外的其他类型的属性不会被克隆,因此当通过新对象对这些属性进行修改时,原对象的属性也会同时改变。而深克隆则已经对这些属性重新分配内存,所以当通过新对象对这些属性进行修改时,原对象的属性不会改变。

3 测试

1.浅克隆

Dogs

复制代码
package images;

public class Dogs implements  Cloneable{
    private  int id;
    private  Cat cat;

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

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

    public int getId() {
        return id;
    }

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

    public Cat getCat() {
        return cat;
    }

    public void setCat(Cat cat) {
        this.cat = cat;
    }

    @Override
    public String toString() {
        return "Dogs{" + "id=" + id + ", " + cat.toString() + '}';
    }
}
View Code
复制代码

Cat

复制代码
package images;

public class Cat {
private  int id;
private  String name;

    public Cat(int id, String name) {
        this.id = id;
        this.name = name;
    }

    public int getId() {
        return id;
    }

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

    public String getName() {
        return name;
    }

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

    @Override
    public String toString() {
        return "Cat{" +
                "id=" + id +
                ", name='" + name + '\'' +
                '}';
    }
}
View Code
复制代码

Test:

复制代码
package images;

public class Test {
    public static void main(String[] args) {
        Dogs dog1=new Dogs(1);
        Cat cat1=new Cat(1,"cat1");
        dog1.setCat(cat1);

        try {
            Dogs dog2= (Dogs) dog1.clone();
            dog2.setId(2);
            System.out.println("dog1ID:"+dog1.getId()+"  dog2ID:"+dog2.getId());//dog1ID:1  dog2ID:2
            dog2.getCat().setId(2);
            System.out.println(dog1.getCat().getId()+"    "+dog2.getCat().getId());//2
            System.out.println(dog1.getClass()==dog2.getClass());//true
            System.out.println(dog1.getCat().getClass()==dog2.getCat().getClass());//true
            System.out.println(dog1==dog2);//false
            System.out.println(dog1.getCat()==(dog2.getCat()));//true




        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }

    }
}
View Code
复制代码

2 深克隆

Dogs

复制代码
package images;

import com.sun.xml.internal.messaging.saaj.util.ByteOutputStream;

import java.io.*;
import java.util.Arrays;

public class Dogs implements  Cloneable, Serializable {
    private  int id;
    private  Cat cat;

    @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)
        {
            System.out.println("克隆出错"+ Arrays.toString(e.getStackTrace()));
            return null;
        }
    }

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

    public int getId() {
        return id;
    }

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

    public Cat getCat() {
        return cat;
    }

    public void setCat(Cat cat) {
        this.cat = cat;
    }

    @Override
    public String toString() {
        return "Dogs{" + "id=" + id + ", " + cat.toString() + '}';
    }
}
View Code
复制代码

Cat

复制代码
package images;

import java.io.Serializable;

public class Cat implements  Cloneable, Serializable {
private  int id;
private  String name;

    public Cat(int id, String name) {
        this.id = id;
        this.name = name;
    }

    public int getId() {
        return id;
    }

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

    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 "Cat{" +
                "id=" + id +
                ", name='" + name + '\'' +
                '}';
    }
}
View Code
复制代码

Test:

复制代码
package images;

public class Test {
    public static void main(String[] args) {


        try {      Dogs dog1=new Dogs(1);
            Cat cat1=new Cat(1,"cat1");
            dog1.setCat(cat1);
            Dogs dog2= (Dogs) dog1.clone();

            dog2.setId(2);
            System.out.println("dog1ID:"+dog1.getId()+"  dog2ID:"+dog2.getId());//dog1ID:1  dog2ID:2
            dog2.getCat().setId(2);
            System.out.println(dog1.getCat().getId()+"    "+dog2.getCat().getId());//1   2
            System.out.println(dog1.getClass()==dog2.getClass());//true
            System.out.println(dog1.getCat().getClass()==dog2.getCat().getClass());//true
            System.out.println(dog1==dog2);//false
            System.out.println(dog1.getCat()==(dog2.getCat()));//false




        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }

    }
}
View Code
复制代码

 

4 总结

深克隆的实现有两种方式:

①实现Cloneable接口并重写Object类中的clone()方法;
②实现Serializable接口,通过对象的序列化和反序列化实现克隆,可以实现真正的深度克隆。

浅克隆是指拷贝对象时仅仅拷贝对象本身(包括对象中的基本变量),而不拷贝对象包含的引用指向的对象。
深克隆不仅拷贝对象本身,而且拷贝对象包含的引用指向的所有对象

 5 参考

理解深克隆和浅克隆_一层沙的博客-CSDN博客_深克隆和浅克隆

posted @   blakee  阅读(420)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
点击右上角即可分享
微信分享提示