Java中浅拷贝与深拷贝之间的区别

 

在深入探讨Java中浅表副本与深表副本之间的差异之前,让我们看看首先进行克隆的是什么。

 

什么是克隆?

克隆是在内存中创建现有对象的精确副本的过程。在Java中,java.lang.Object类的clone()方法用于克隆过程。此方法创建一个对象的精确副本,并通过逐字段分配在其上对其进行调用,并返回该对象的引用。并非Java中的所有对象都适用于克隆过程。实现Cloneable接口的对象仅适用于克隆过程。可克隆接口是 标记器接口,用于为克隆过程提供标记。单击此处以查看有关Java中clone()方法的更多信息。

浅拷贝和深拷贝都与此克隆过程有关。默认版本的clone()方法创建对象的浅表副本。要创建对象的深层副本,您必须重写clone()方法。让我们看看这些浅拷贝和深拷贝是如何工作的。

Java中的浅表复制:

默认版本的clone()方法创建对象的浅表副本。对象的浅表副本将具有原始对象所有字段的精确副本。如果原始对象具有对其他对象的任何引用作为字段,则仅将那些对象的引用复制到克隆对象中,而不创建这些对象的副本。这意味着通过克隆对象对这些对象所做的任何更改都将反映在原始对象中,反之亦然。浅拷贝并非与原始对象100%脱离。浅拷贝不是100%独立于原始对象。

下面是创建对象“ student1 ”的浅表副本的示例

1个
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18岁
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65岁
66
67
68
69
70
71
72
73
74
75
76
77
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 ”类的对象,它具有三个字段-idnamecourse。“课程”是指向“课程”类型对象的参考变量。“ student1 ”的克隆是通过调用克隆方法创建的,并将其分配给“ student2 ”。当克隆方法的默认版本创建浅表副本时,“ student1 ”和“ student2 ”的“课程”字段将指向相同的“课程”对象。因此,通过' student2对该对象进行的任何更改将会反映在“ student1 ”中,反之亦然。

请参阅下面的图片以获得更清晰的了解。

 

Java中的浅表复制与深表复制

 

Java深拷贝:

对象的深层副本将具有原始对象所有字段的精确副本,就像浅层副本一样。但另外,如果原始对象具有对其他对象的任何引用作为字段,则还可以通过在它们上调用clone()方法来创建这些对象的副本。这意味着克隆对象和原始对象将是100%不相交的。他们将彼此100%独立。对克隆对象所做的任何更改都不会反映在原始对象中,反之亦然。

要创建对象的深层副本,您必须重写clone()方法,如以下示例所示。

1个
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18岁
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65岁
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
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”的深层副本。

Java中的浅表复制与深表复制

 

浅拷贝与深拷贝在Java中:

以下是Java中浅表复制和深表复制之间的差异列表。

浅拷贝深拷贝
克隆对象和原始对象不是100%不相交的。克隆对象和原始对象是100%不相交的。
对克隆对象所做的任何更改都将反映在原始对象中,反之亦然。对克隆对象所做的任何更改都不会反映在原始对象中,反之亦然。
默认版本的clone方法创建对象的浅表副本。要创建对象的深层副本,您必须重写clone方法。
如果对象只有原始字段,则首选浅复制。如果对象具有对其他对象的引用作为字段,则首选深度复制。
浅拷贝速度快,而且价格便宜。深拷贝很慢,而且非常昂贵。

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值