Java之深拷贝与浅拷贝的理解

Java之深拷贝与浅拷贝的理解


前言

拷贝一词大家都不陌生,在我们日常使用计算机的时候,Ctrl+C就是一种拷贝,但是在java中拷贝有不同的方式,在拷贝的类型上也会有不一样的地方。


提示:以下是本篇文章正文内容,下面案例可供参考

1、引用拷贝

拷贝一个对象的引用,例如

public class Clone {
    public static void main(String[] args) {
        Student s = new Student("张三");
        Student s1 = s;
        System.out.println(s+"+"+s1);
    }
    private static class Student implements Cloneable{
        private String name;
        Student(String name){
            this.name=name;
        }

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

打印出来结果为
在这里插入图片描述
所以也就表示,s与s1指向的是同一个对象,都是Student

这就是引用拷贝。

2、对象拷贝

对象拷贝也就是创建一个对象的副本。

 public static void main(String[] args) throws CloneNotSupportedException{
        Student s = new Student("张三");
        Student s1 = (Student) s.clone();
        System.out.println(s+"+"+s1);
    }


public class Student implements Cloneable{
        private String name;
        Student(String name){
            this.name=name;
        }

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

         public Object clone() throws CloneNotSupportedException {
        Object object = super.clone();
        return object;
    }
    }

调用Object中的clone方法之后可以看到

在这里插入图片描述
现在s与s1 的地址是不同的,所以是创建了一个新的对象。

浅拷贝与深拷贝

浅拷贝与深拷贝都为对象拷贝

浅拷贝

被复制对象的所有变量都含有与原来的对象相同的值,而所有的对其他对象的引用仍然指向原来的对象。即对象的浅拷贝会对“主”对象进行拷贝,但不会复制主对象里面的对象。”里面的对象“会在原来的对象和它的副本之间共享。

public class Clone{
    public static void main(String[] args) throws CloneNotSupportedException {
        Teacher teacher = new Teacher();
        teacher.setName("张三");
        Student student1 = new Student();
        student1.setName("李四");
        student1.setTeacher(teacher);

        Student student2 = (Student) student1.clone();
        System.out.println(student2.getTeacher().getName());
        System.out.println(student2.getTeacher().getAge());
        teacher.setName("jack");
        System.out.println( student1.getTeacher().getName());
        System.out.println(student2.getTeacher().getName());

    }
}

class Teacher implements Cloneable {
    private String name;
   
    public String getName() {
        return name;
    }

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

class Student implements Cloneable {
    private String name;
    private Teacher teacher;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
    public Teacher getTeacher() {
        return teacher;
    }
    public void setTeacher(Teacher teacher) {
        this.teacher = teacher;
    }
    public Object clone() throws CloneNotSupportedException {
        Object object = super.clone();
        return object;
    }
}

最后结果为
在这里插入图片描述
也就是说明,这两个学生对象中的Teacher对象是同一个。改变一个也就改变了另外一个。

深拷贝

深拷贝是一个整个独立的对象拷贝,深拷贝会拷贝所有的属性,并拷贝属性指向的动态分配的内存。当对象和它所引用的对象一起拷贝时即发生深拷贝。深拷贝相比于浅拷贝速度较慢并且花销较大。

    public Object clone() throws CloneNotSupportedException {
        // 浅复制时:
        // Object object = super.clone();
        // return object;

        // 改为深复制:
        Student student = (Student) super.clone();
        // 本来是浅复制,现在将Teacher对象复制一份并重新set进来
        student.setTeacher((Teacher) student.getTeacher().clone());
        return student;

    }

这里和浅拷贝唯一的不同在于,在浅拷贝时时直接把对象的引用拷贝了进去,但是深拷贝的改变就是,在浅拷贝时,把被拷贝的对象中的对象依旧拷贝了一份放入了要拷贝对象中。

在这里插入图片描述

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Java 中,深拷贝(Deep Copy)和浅拷贝(Shallow Copy)是用于描述对象拷贝的概念。 浅拷贝是指创建一个新对象,新对象的属性值和原对象的属性值相同,但是对于引用类型的属性,新旧对象将共享同一个引用。也就是说,新旧对象的引用类型属性指向同一个内存地址。 深拷贝则是在拷贝对象时,不仅会复制对象本身,还会递归复制对象的引用类型属性,使得新对象和原对象的引用类型属性指向不同的内存地址。 Java 中的默认拷贝行为是浅拷贝。可以通过以下两种方式实现深拷贝: 1. 实现 `Cloneable` 接口并重写 `clone()` 方法:这是一种较为简单的实现深拷贝的方式。在需要进行深拷贝的类中,实现 `Cloneable` 接口,并重写 `clone()` 方法,在 `clone()` 方法中递归复制引用类型的属性。 ```java class MyClass implements Cloneable { private int number; private MyObject myObject; // constructors, getters, setters @Override protected Object clone() throws CloneNotSupportedException { MyClass cloned = (MyClass) super.clone(); cloned.myObject = (MyObject) myObject.clone(); // 实现 MyObject 的 clone() 方法 return cloned; } } ``` 通过调用 `clone()` 方法来创建一个新的深拷贝对象:`MyClass clonedObject = (MyClass) originalObject.clone();` 2. 使用序列化和反序列化:这是另一种实现深拷贝的方式。通过将对象序列化为字节流,然后再将字节流反序列化为新的对象,可以实现深拷贝。这种方式需要确保对象及其引用类型属性都是可序列化的。 ```java import java.io.*; class MyClass implements Serializable { // class definition } ``` ```java // 实现深拷贝的方法 public static <T extends Serializable> T deepCopy(T object) throws IOException, ClassNotFoundException { ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); ObjectOutputStream objectOutputStream = new ObjectOutputStream(outputStream); objectOutputStream.writeObject(object); ByteArrayInputStream inputStream = new ByteArrayInputStream(outputStream.toByteArray()); ObjectInputStream objectInputStream = new ObjectInputStream(inputStream); return (T) objectInputStream.readObject(); } ``` 通过调用 `deepCopy()` 方法来创建一个新的深拷贝对象:`MyClass clonedObject = deepCopy(originalObject);` 需要注意的是,为了实现深拷贝,引用类型的类也需要实现 `Cloneable` 接口并重写 `clone()` 方法,或者是可序列化的。 希望这些信息对你有所帮助。如果你还有其他问题,请随时提问。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值