Java中要想自定义类的对象可以被复制,自定义类就必须实现Cloneable中的clone()方法,如下:
public class Student implements Cloneable { private String name; private int age; private Professor professor; public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public Professor getProfessor() { return professor; } public void setProfessor(Professor professor) { this.professor = professor; } @Override public String toString() { return "Student [name=" + name + ", age=" + age + ", professor=" + professor + "]"; } public Object clone() throws CloneNotSupportedException{ return super.clone(); } }
其中,Professor类同样为自定义类:
public class Professor { private String name; private int age; public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } @Override public String toString() { return "Professor [name=" + name + ", age=" + age + "]"; } }
然而,当自定义类的字段的类型不是基本数据类型时,上面实现了clone()方法会导致问题,不信看下面的代码:
【程序实例1】
public class ShadowCopy { public static void main(String[] args) { Professor p1 = new Professor(); p1.setName("Professor Zhang"); p1.setAge(30); Student s1 = new Student(); s1.setName("xiao ming"); s1.setAge(18); s1.setProfessor(p1); System.out.println(s1); try { Student s2 = (Student) s1.clone(); Professor p2 = s2.getProfessor(); p2.setName("Professor Li"); p2.setAge(45); s2.setProfessor(p2); System.out.println("复制后的:s1 = " + s1); System.out.println("复制后的:s2 = " + s2); } catch (CloneNotSupportedException e) { e.printStackTrace(); } } }
【运行结果1】
1 Student [name=xiao ming, age=18, professor=Professor [name=Professor Zhang, age=30]] 2 复制后的:s1 = Student [name=xiao ming, age=18, professor=Professor [name=Professor Li, age=45]] 3 复制后的:s2 = Student [name=xiao ming, age=18, professor=Professor [name=Professor Li, age=45]]
【结果分析】
学生s1的导师为30岁的Professor Zhang,恰好学生s2与学生s1同名同岁,但是s2的导师为45岁的Professor Li,于是我们顺理成章地复制复制s1并复制给s2,再修改下s2的导师的信息。可是,问题出现了,当我们修改了s2的导师后,s2的信息是对了,但是s1的导师信息也跟着修改了,这可不是我们期望的。
【问题分析】
程序实例1中的问题出在哪儿呢?我们已经对Student类实现了clone()方法,怎么还是出问题了呢?我们在看下面的代码:
【程序实例2】
public class ShadowCopy { public static void main(String[] args) { Professor p1 = new Professor(); p1.setName("Professor Zhang"); p1.setAge(30); Student s1 = new Student(); s1.setName("xiao ming"); s1.setAge(18); s1.setProfessor(p1); System.out.println(s1); try { Student s2 = (Student) s1.clone(); s2.setName("xiao hong"); s2.setAge(17); Professor p2 = s2.getProfessor(); p2.setName("Professor Li"); p2.setAge(45); s2.setProfessor(p2); System.out.println("复制后的:s1 = " + s1); System.out.println("复制后的:s2 = " + s2); } catch (CloneNotSupportedException e) { e.printStackTrace(); } } }
【运行结果】
1 Student [name=xiao ming, age=18, professor=Professor [name=Professor Zhang, age=30]] 2 复制后的:s1 = Student [name=xiao ming, age=18, professor=Professor [name=Professor Li, age=45]] 3 复制后的:s2 = Student [name=xiao hong, age=17, professor=Professor [name=Professor Li, age=45]]
【结果分析】
这次,我们在clone后,又修改了s2的name和age,从结果可以看出,s1的name和age并没有因为s2的修改而改变。
结合程序实例1和程序实例2,我们发现Student的字段如果不是一个引用时,修改clone()得到对象的该字段(name, age)时并不会影响原来的对象,但是当字段为一个引用时,修改clone()得到对象的该字段(professor)时并会影响原来的对象。上面实现的clone()方法为浅复制(shadow copy)。
如果想要clone()得到的新对象的修改不会影响被复制的对象的字段时,我们就需要实现深复制(deep copy),代码修改如下:
public class Professor implements Cloneable { private String name; private int age; public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } @Override public String toString() { return "Professor [name=" + name + ", age=" + age + "]"; } public Object clone() throws CloneNotSupportedException{ return super.clone(); } }
public class Student implements Cloneable { private String name; private int age; private Professor professor; public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public Professor getProfessor() { return professor; } public void setProfessor(Professor professor) { this.professor = professor; } @Override public String toString() { return "Student [name=" + name + ", age=" + age + ", professor=" + professor + "]"; } public Object clone() throws CloneNotSupportedException{ Student newStudent = (Student) super.clone(); newStudent.professor = (Professor) professor.clone(); return newStudent; } }
再次运行【程序实例2】得到的结果为:
1 Student [name=xiao ming, age=18, professor=Professor [name=Professor Zhang, age=30]] 2 复制后的:s1 = Student [name=xiao ming, age=18, professor=Professor [name=Professor Zhang, age=30]] 3 复制后的:s2 = Student [name=xiao hong, age=17, professor=Professor [name=Professor Li, age=45]]
可以看到:修改clone()得到的s2的任何字段都不会影响s1的字段,这也就是深复制的作用。
相关推荐
深复制的实现通常需要自定义逻辑,因为Java的`clone()`方法不支持自动的深复制。可以使用序列化(Serialization)和反序列化(Deserialization)来实现深复制,或者手动编写代码递归复制所有属性。例如: ```java ...
### Java的深复制与浅复制 #### 一、概述 在Java编程中,对象的复制是一个常见的需求。复制对象的目的通常是为了保留一个备份或者创建一个新的实例来避免对原始对象的修改影响到其他部分的程序逻辑。Java提供了两...
Java Clone 深拷贝与浅拷贝的两种实现方法 Java Clone 是 Java 语言中的一种复制对象的机制,它可以将一个对象的所有属性和状态复制到另一个对象中,实现对象的深拷贝和浅拷贝。下面我们将讨论 Java 中的深拷贝和浅...
以下是一个简单的例子,展示了如何实现深复制: ```java class Student implements Cloneable { String name; int age; Professor professor; // 构造函数、getter、setter略... @Override protected ...
本篇文章将深入探讨Java中的深复制和浅复制概念,并通过源代码示例进行详细解析。 首先,我们理解一下深复制和浅复制的区别: 1. **浅复制(Shallow Copy)**:浅复制只是复制了对象的引用,而不是对象本身。这...
在Java中,当我们使用`clone()`方法或`System.arraycopy()`进行复制时,通常得到的是浅复制的结果。这意味着原始对象和复制对象中的引用指向内存中的同一块区域。如果List中的元素是基本类型,这种复制方式是没问题...
在编程领域,尤其是在Java语言中,深复制和浅复制是两个重要的概念,它们与对象的复制行为密切相关。这里我们将深入探讨这两个概念,并通过实例来解释它们的区别。 首先,让我们了解基本数据类型的复制。在Java中,...
对象复制分为两种主要类型:浅复制(浅克隆)和深复制(深克隆)。理解这两种复制方式的区别对于优化程序性能和避免意外数据更改至关重要。 1. **浅复制(浅克隆)** 浅复制是指创建一个新对象,该对象拥有原始...
### Java中的`clone`方法详解:浅拷贝与深拷贝 #### 一、引言 在Java中,`clone`方法提供了一种快速复制对象的方式。它属于`Object`类的一部分,但需要显式地在子类中声明并实现`Cloneable`接口才能正常使用。本文...
在本文中,我们将深入探讨Java中的浅克隆(shallow clone)和深克隆(deep clone),并结合测试代码进行分析。 首先,让我们理解`Cloneable`接口。在Java中,如果一个类想要支持`clone()`方法,它必须实现`...
本文将深入探讨Java中的浅复制和深复制,并以Android为背景,结合具体的实例讲解如何实现Java泛型深拷贝。 首先,我们要理解浅复制和深复制的概念。浅复制(Shallow Copy)是指创建一个新的对象,然后将原对象引用...
在Java编程语言中,`clone()`方法是一个非常重要的概念,特别是在对象复制和克隆方面。这个小例子将帮助初学者理解如何在Java中使用`clone()`来创建对象的副本。让我们深入探讨`clone()`方法以及它在实际编程中的...
在Java中,对象的默认复制是浅复制(shallow copy),这意味着只复制对象本身,而不复制它引用的对象。要实现深复制(deep copy),需要自定义`clone()`方法。下面我们将详细探讨Java中的克隆以及提供的实例代码。 ...
为了理解深拷贝(深复制)和浅拷贝(浅复制),我们需要首先了解Java对象内存的分配方式以及引用的概念。 1. **对象复制的基础** 在Java中,当我们创建一个对象时,系统会在内存中为该对象分配一块空间,存储它的...
在Java编程中,深复制和浅复制是两个重要的概念,主要涉及到对象的复制与克隆。这两个术语在处理对象的拷贝时具有不同的含义,理解它们对于编写高效且无误的代码至关重要。 首先,让我们来看一下浅复制(Shallow ...
在Java中,`clone`方法主要用于创建一个现有对象的副本,这个副本与原始对象具有相同的数据值。这个方法是Object类的一个成员,因此所有的Java类都默认拥有`clone`方法。不过,需要注意的是,`clone`方法并不执行深...
例如,如果`CloneClass`有一个`UnCloneA`类型的成员变量,为了实现深克隆,我们需要在`clone`方法中对`UnCloneA`对象进行复制: ```java @Override protected Object clone() throws CloneNotSupportedException { ...
Java对象深复制与浅复制实例详解 Java对象深复制与浅复制是Java编程中两个重要的概念,它们都是对象复制的方式,但它们有着不同的实现机制和应用场景。在本文中,我们将详细介绍Java对象深复制与浅复制的概念、实现...
Java提供了两种主要的克隆方式:深克隆和浅克隆。 1. 浅克隆(Shallow Clone): 浅克隆是通过调用对象的`clone()`方法来实现的,这个方法是Object类提供的。当一个对象被浅克隆时,新创建的对象将拥有原始对象的...
Java提供了两种主要的克隆方式:浅克隆(Shallow Clone)和深克隆(Deep Clone)。下面我们将深入探讨这两种克隆方法。 ### 浅克隆 浅克隆是指创建一个新的对象,其成员变量的值与原对象相同,但引用类型成员变量...