浅拷贝(shallow copy)和深拷贝(deep copy)

浅拷贝(shallow copy):只负责克隆按值传递的数据(比如基本数据类型、String类型)

深拷贝(deep copy):除了shallow copy的值外,还负责克隆引用类型的数据,基本是就是被克隆实例所有的属性数据都会被克隆出来。

这里推荐一篇介绍非常详细的外文文章

Difference Between Shallow Copy Vs Deep Copy In Java

什么是克隆?

克隆就是在内存中拷贝一份已有对象的过程。Java中java.lang.Object类中的方法clone()就是作为克隆用的。这个方法会把实例对象逐个字段的值原样拷贝过来,对于引用类型则是把对应的内存地址拷贝过来。不过不是所有类都能使用克隆方法,需要实现Cloneable接口。Cloneable接口是一个标识接口,仅做标记之用,接口中未声明任何方法。 

浅拷贝和深拷贝就是克隆相关的两种方法。默认clone()方法实现的是浅拷贝。如果要实现深拷贝,需要覆盖clone()方法。下面开始详细介绍浅拷贝和深拷贝

Java中的浅拷贝:

Java中默认的clone()方法就是浅拷贝,即拷贝原有对象的值。如果原有对象有任何引用对象,则引用对象的属性值会拷贝过去,但不会创建新的对象(译者注:也就是说只是把内存地址拷贝过去,并未创建新的实例)。这就意味着任何对这些被克隆对象的修改都会导致克隆对象发生相同的变动,反之亦然。浅拷贝不是百分百与原有对象保持独立的关系,会互相影响。

class Course
{
    String subject1;
 
    String subject2;
 
    String subject3;
 
    public Course(String sub1, String sub2, String sub3)
    {
        this.subject1 = sub1;
 
        this.subject2 = sub2;
 
        this.subject3 = sub3;
    }
}
 
class Student implements Cloneable
{
    int id;
 
    String name;
 
    Course course;
 
    public Student(int id, String name, Course course)
    {
        this.id = id;
 
        this.name = name;
 
        this.course = course;
    }
 
    //Default version of clone() method. It creates shallow copy of an object.
 
    protected Object clone() throws CloneNotSupportedException
    {
        return super.clone();
    }
}
 
public class ShallowCopyInJava
{
    public static void main(String[] args)
    {
        Course science = new Course("Physics", "Chemistry", "Biology");
 
        Student student1 = new Student(111, "John", science);
 
        Student student2 = null;
 
        try
        {
            //Creating a clone of student1 and assigning it to student2
 
            student2 = (Student) student1.clone();
        }
        catch (CloneNotSupportedException e)
        {
            e.printStackTrace();
        }
 
        //Printing the subject3 of 'student1'
 
        System.out.println(student1.course.subject3);         //Output : Biology
 
        //Changing the subject3 of 'student2'
 
        student2.course.subject3 = "Maths";
 
        //This change will be reflected in original student 'student1'
 
        System.out.println(student1.course.subject3);       //Output : Maths
    }
}

在上面的例子中,student1是Student类的一个对象实例,有三个字段,分别是id,name,course。course是个指向Course的引用对象,student2是通过克隆student1创建出来。通过浅拷贝,course字段的默认值在student1和student2是一样的,都指向Course对象。因此,任何对对象student2的改动都会反映到student1中,反之亦然。

shallow copy vs deep copy in java

Java中的深拷贝:

深拷贝很像浅拷贝,也会拷贝实例对象的值,但是不同的是,会额外再创建引用对象的实例。这也就意味着克隆对象与原型对象是互相分离的,独立互不影响的。任何对克隆对象的更改不会对原型对象产生任何影响。

如果要创建深拷贝,需要覆盖clone()方法,如下代码所示:

class Course implements Cloneable
{
    String subject1;
 
    String subject2;
 
    String subject3;
 
    public Course(String sub1, String sub2, String sub3)
    {
        this.subject1 = sub1;
 
        this.subject2 = sub2;
 
        this.subject3 = sub3;
    }
 
    protected Object clone() throws CloneNotSupportedException
    {
        return super.clone();
    }
}
 
class Student implements Cloneable
{
    int id;
 
    String name;
 
    Course course;
 
    public Student(int id, String name, Course course)
    {
        this.id = id;
 
        this.name = name;
 
        this.course = course;
    }
 
    //Overriding clone() method to create a deep copy of an object.
 
    protected Object clone() throws CloneNotSupportedException
    {
        Student student = (Student) super.clone();
 
        student.course = (Course) course.clone();
 
        return student;
    }
}
 
public class DeepCopyInJava
{
    public static void main(String[] args)
    {
        Course science = new Course("Physics", "Chemistry", "Biology");
 
        Student student1 = new Student(111, "John", science);
 
        Student student2 = null;
 
        try
        {
            //Creating a clone of student1 and assigning it to student2
 
            student2 = (Student) student1.clone();
        }
        catch (CloneNotSupportedException e)
        {
            e.printStackTrace();
        }
 
        //Printing the subject3 of 'student1'
 
        System.out.println(student1.course.subject3);         //Output : Biology
 
        //Changing the subject3 of 'student2'
 
        student2.course.subject3 = "Maths";
 
        //This change will not be reflected in original student 'student1'
 
        System.out.println(student1.course.subject3);       //Output : Biology
    }
}

下图展示了student1如何被创建

shallow copy vs deep copy in java

Java中浅拷贝和深拷贝可用如下表格作对比:

浅拷贝

深拷贝

拷贝对象与原型对象不是绝对分离的

拷贝对象与原型对象绝对分离

对拷贝对象的更改会影响到原型对象

对拷贝对象的更改不会影响到原型对象

默认的clone()方法只是浅拷贝

要创建深拷贝需要覆盖clone()方法

浅拷贝只推荐实例对象是基本数据类型的情况

如果是除基本类型以外的对象,推荐深拷贝

浅拷贝速度快,开销低

深拷贝速度慢,开销高

 

这里推荐两篇文章,也是对浅拷贝和深拷贝讲述的比较好,可以看看,会有帮助

漫谈deepcopy(深拷贝)和shallowcopy(浅拷贝)

What is the difference between a deep copy and a shallow copy

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在Python中,拷贝指的是创建一个新的对象,包含原始对象的所有内容。但是,拷贝拷贝会根据拷贝方式的不同,影响拷贝结果。 拷贝Deep Copy)是指创建一个新的对象,包含原始对象的所有内容,甚至包括原始对象中引用的对象。也就是说,拷贝会递归地复制所有对象,包括它们的内部对象。拷贝的结果是两个完全独立的对象,修改一个对象不会影响另一个对象。 拷贝Shallow Copy)是指创建一个新的对象,包含原始对象的所有内容,但不会递归复制原始对象中引用的对象。也就是说,拷贝只复制对象的顶层内容,而不会对其内部对象进行复制。拷贝的结果是两个对象共享同一个内部对象,修改一个对象会影响另一个对象。 下面是一个例子,可以更好地说明拷贝拷贝的区别: ```python import copy # 定义一个列表 a = [1, 2, [3, 4]] # 拷贝 b = copy.copy(a) # 拷贝 c = copy.deepcopy(a) # 修改a的第二个元素 a[1] = 5 # 修改a的第三个元素中的第一个元素 a[2][0] = 6 # 输出a、b、c的值 print(a) # [1, 5, [6, 4]] print(b) # [1, 2, [6, 4]] print(c) # [1, 2, [3, 4]] ``` 在上面的例子中,我们先定义了一个列表a,它包含了一个嵌套列表。我们使用copy.copy()和copy.deepcopy()对a进行拷贝,并修改原始列表a的值。最后,我们输出了三个列表的值,可以看到,拷贝b的第三个元素的值也被修改了,而拷贝c的值没有受到影响。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值