Java中对象的浅拷贝与深拷贝
- 格式:docx
- 大小:94.79 KB
- 文档页数:8
本文由我司收集整编,推荐下载,如有疑问,请与我司联系Java 中的深拷贝与浅拷贝2017/05/01 0 Java 中有两种拷贝方式一种是浅拷贝,一种是深拷贝。
两者的区别也很好阐述:浅拷贝它只是简单拷贝对象成员的引用,而深拷贝则会重新生成一个对象副本。
当然String 这些对象比较特殊。
举个实例:(注意看注释)package clone;public class Teacher implements Cloneable {public String name;public int age;public Teacher(String name, int age) {super(); = name;this.age = age;}@Overridepublic Object clone() {Object obj=null;try {obj=super.clone();} catch (CloneNotSupportedException e) {// TODO Auto-generated catch blocke.printStackTrace();}return obj;}@Overridepublic String toString() {return Teacher [name= + name + , age= + age + ] }}package clone;public class Student implementsCloneable {public Teacher teacher;public String name;public int age;public Student(Teacher teacher, String name, int age) {super();this.teacher = teacher; =name;this.age = age;}//浅拷贝@Overridepublic Object clone() {Object obj=null;try {obj=super.clone();} catch (CloneNotSupportedException e) {// TODO Auto-generated catch blocke.printStackTrace();}return obj;}//深拷贝public Student clone(boolean flag) {Student student=null;try {student=(Student) super.clone();} catch (CloneNotSupportedException e) {// TODO Auto-generated catch blocke.printStackTrace();}student.teacher=(Teacher)student.teacher.clone();returnstudent;}@Overridepublic String toString() {return Student [teacher= + teacher + , name= + name + , age= + age + ] }}package clone;public class Client {public static void main(String[] args) {// TODO Auto-generated method stubTeacher teacher;Student student;Student clone_student;teacher=new Teacher( 程老师, 20);student=new Student(teacher, 小猿, 12);//浅拷贝clone_student=(Student) student.clone();System.out.println(teacher);clone_student.age=18;clone_= 大猿//改变int 和String 不会影响原本的类clone_student.teacher.age=40; //改变对象。
Javaclone()⽅法克隆对象——深拷贝与浅拷贝基本数据类型引⽤数据类型特点1、基本数据类型的特点:直接存储在栈(stack)中的数据2、引⽤数据类型的特点:存储的是该对象在栈中引⽤,真实的数据存放在堆内存⾥引⽤数据类型在栈中存储了指针,该指针指向堆中该实体的起始地址。
当解释器寻找引⽤值时,会⾸先检索其在栈中的地址,取得地址后从堆中获得实体。
深拷贝与浅拷贝特点浅拷贝只复制指向某个对象的指针,⽽不复制对象本⾝,新旧对象还是共享同⼀块内存。
但深拷贝会另外创造⼀个⼀模⼀样的对象,新对象跟原对象不共享内存,修改新对象不会改到原对象。
当把⼀个对象赋值给⼀个新的变量时,赋的其实是该对象的在栈中的地址,⽽不是堆中的数据。
也就是两个对象指向的是同⼀个存储空间,⽆论哪个对象发⽣改变,其实都是改变的存储空间的内容,因此,两个对象是联动的。
浅拷贝是按位拷贝对象,它会创建⼀个新对象,这个对象有着原始对象属性值的⼀份精确拷贝。
如果属性是基本类型,拷贝的就是基本类型的值;如果属性是内存地址(引⽤类型),拷贝的就是内存地址,因此如果其中⼀个对象改变了这个地址,就会影响到另⼀个对象。
即默认拷贝构造函数只是对对象进⾏浅拷贝复制(逐个成员依次拷贝),即只复制对象空间⽽不复制资源。
Java clone⽅法深拷贝与浅拷贝clone浅拷贝由CloneDemo类可以看出,没有重写clone⽅法,对象中的引⽤数据类型只是复制了该引⽤数据类型的引⽤,并没有在内存空间中开辟空间复制该引⽤数据类型,即对该引⽤数据类型进⾏了浅拷贝⽽不是深拷贝。
package ng;public class CloneDemo implements Cloneable {private int num;private String name;private Helper helper;public CloneDemo() {}public int getNum() {return num;}public void setNum(int num) {this.num = num;}public String getName() {return name;}public void setName(String name) { = name;}public Helper getHelper() {return helper;}@Overridepublic String toString() {return "CloneDemo{" +"num=" + num +", name='" + name + '\'' +", helper=" + helper +'}';}public void setHelper(Helper helper) {this.helper = helper;}public static class Helper {public int num;public Helper(int num) {this.num = num;}public int getNum() {return num;}public void setNum(int num) {this.num = num;}@Overridepublic String toString() {return "Helper{" +"num=" + num +'}';}}public static void main(String[] args) throws CloneNotSupportedException { CloneDemo d1 = new CloneDemo();d1.setName("Jack");d1.setNum(10);d1.setHelper(new Helper(100));CloneDemo d2 = (CloneDemo) d1.clone();System.out.println( == );System.out.println(d1.num == d2.num);System.out.println(d1.helper == d2.helper);d2.setNum(11);d2.setName("json");d2.getHelper().setNum(101);System.out.println();System.out.println(d1.num);System.out.println(d1.helper.toString());System.out.println();System.out.println(d2.num);System.out.println(d2.helper.toString());/* Output:truetruetrueJack10Helper{num=101}json11Helper{num=101}*/}}clone深拷贝对Helper类和CloneDemo都重写clone⽅法:CloneDemo重写clone⽅法:@Overrideprotected CloneDemo clone() throws CloneNotSupportedException {CloneDemo clone = (CloneDemo1) super.clone();clone.helper = helper.clone();return clone;}Helper重写clone⽅法:@Overrideprotected Helper clone() throws CloneNotSupportedException {Helper helper = null;Helper clone = (Helper) super.clone();return clone;}输出结果:结果显⽰,对Helper类和CloneDemo都重写clone⽅法后,实现了对引⽤数据类型Helper的深拷贝。
谈谈java中对象的深拷贝与浅拷贝知识点:java中关于Object.clone⽅法,对象的深拷贝与浅拷贝引⾔:在⼀些场景中,我们需要获取到⼀个对象的拷贝,这时候就可以⽤java中的Object.clone⽅法进⾏对象的复制,得到⼀个⼀模⼀样的新对象。
(使⽤new再次创建⼀个相同的对象也是可以的,有些区别),当对象中含有可变的引⽤类型属性时,在复制得到的新对象对该引⽤类型属性内容进⾏修改,原始对象相应的属性内容也会发⽣变化,这就是"浅拷贝"的现象。
反之原始对象相应的引⽤类型属性不发⽣变化,是"深拷贝"。
浅拷贝先看⼀个浅拷贝的demo实例1.创建⼀个Person类public class Person implements Cloneable{private String name;private int age;private Address address;//构造⽅法public Person(String name, int age, Address address) { = name;this.age = age;this.address = address;}@Overrideprotected Object clone() throws CloneNotSupportedException {return super.clone();}public String display(){return "Person[name="+name+",age="+age+",address"+address+"]";}public String getName() {return name;}public void setName(String name) { = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}public Address getAddress() {return address;}public void setAddress(Address address) {this.address = address;}}由于clone()⽅法是protected修饰的,因此需要实现Cloneable接⼝才能调⽤,同时需要覆写clone()⽅法才能调⽤。
java中的拷贝方法Java 中的拷贝方法是一个非常重要的概念,在开发和设计Java 程序时经常会用到。
拷贝是指将一个对象的所有属性值复制到另一个对象中,这样许多重要操作就可以对原始对象进行而不影响它的副本。
关于Java 中的拷贝方法,有许多种实现方式,而本文将带您了解其中最常用的类型。
一、什么是拷贝拷贝即是复制某个对象的值或属性到另一个对象中,因此拷贝是一种非常重要的操作,可以在许多场景中使用,如保留原有数据、线程操作中使用等。
Java 中的拷贝操作分为两种:浅拷贝和深拷贝。
1.浅拷贝浅拷贝是指复制对象的顶层成员,顶层成员包括基本数据类型和对象类型,但是不包括其它嵌套对象的属性,浅拷贝实际上是复制了对象的引用而不是实际的值。
2.深拷贝深拷贝是指复制对象的所有属性,包括其它嵌套对象的属性,每个对象都可以创建自己的对象副本,这样就可以避免对象引用相同的问题。
二、如何进行浅拷贝Java 中提供了Cloneable 接口以及Object 中的clone() 方法实现对象的浅拷贝,但是还需要重写Object 的clone() 方法,以实现根据对象创建其自己的拷贝。
代码示例:1、首先定义一个需要进行拷贝的Student 类:public class Student implements Cloneable {private String name;private int age;private School school;省略构造方法和getter/setter方法重写clone方法@Overridepublic Object clone() throws CloneNotSupportedException { return super.clone();}}2、创建一个包含嵌套对象的拷贝类School:public class School {private String name;省略构造方法和getter/setter方法重写clone方法@Overridepublic Object clone() throws CloneNotSupportedException { return super.clone();}}3、创建一个测试类来测试上述类的浅拷贝操作:public class Test {public static void main(String[] args) throws CloneNotSupportedException {School school = new School("University of Washington");Student originalStudent = new Student("Alice", 18, school);浅拷贝Student copyStudent = (Student) originalStudent.clone();System.out.println("Original student: " + originalStudent);System.out.println("Copy student: " + copyStudent);System.out.println("Original and copy objects are equal: " + (originalStudent == copyStudent));}}输出结果:Original student: Student{name='Alice', age=18,school=School{name='University of Washington'}}Copy student: Student{name='Alice', age=18,school=School{name='University of Washington'}}Original and copy objects are equal: false从上述结果可以看出,创建的对象之间是相互独立的,但它们引用相同的对象。
Java对象深拷贝浅拷贝总结⽬录在java开发的过程中我们很多时候会有深拷贝需求,⽐如将⼀个请求体拷贝多次,修改成多个不同版笨,分别发给不同的服务,在⽐如维护不同的缓存时。
还有些时候并不需要深拷贝,只是简单的类型转换,⽐如到将do对象转换为dto对象返回给前端,其中两者的字段基本相同,只是类名不⼀样。
本⽂主要罗列了下⾃⼰总结的拷贝⽅式和适合的场景(深浅拷贝原理⽂章很多,本⽂不再解释)。
拷贝过程中⽤到的Bean定义:@Datapublic class Source {String a;Filed1 filed1;Filed1 filed2;List<Filed1> fileds;@NoArgsConstructor@AllArgsConstructor@Datapublic static class Filed1 {String id;}}深拷贝1. ⼿动newSource source = getSource();Source target = new Source();target.setFiled1(new Source.Filed1(source.getFiled1().getId()));target.setFiled2(new Source.Filed1(source.getFiled2().getId()));if (source.getFileds() != null) {ArrayList<Source.Filed1> fileds = new ArrayList<>(source.getFileds().size());for (Source.Filed1 filed : source.getFileds()) {fileds.add(new Source.Filed1(filed.getId()));}target.setFileds(fileds);}⼿动new⾮常简单,但是⾮常繁琐不利于后期的维护,每次修改类定义的时候需要修改相应的copy⽅法,不过性能⾮常⾼。
java 深度复制对象的方法【原创实用版3篇】篇1 目录1.Java 对象复制的必要性2.深度复制和浅度复制的概念3.实现深度复制的几种方法4.实例:使用递归和反射实现深度复制篇1正文在 Java 中,当我们需要复制一个对象时,通常会遇到深度复制和浅度复制的问题。
今天我们将讨论如何实现深度复制。
首先,让我们了解一下深度复制和浅度复制的概念。
浅度复制是指复制对象的基本信息,如引用类型、基本类型等,但不包括对象内部的引用类型。
深度复制则是指复制对象的所有信息,包括对象内部的引用类型。
实现深度复制的方法有很多,下面我们将介绍几种常见的方法。
方法一:使用递归。
递归方法是通过递归调用对象的复制方法来实现深度复制。
具体来说,就是在对象类中实现一个复制方法,该方法会递归地调用对象内部的引用类型,从而达到深度复制的效果。
方法二:使用反射。
反射方法是通过获取对象的类,然后创建该类的新实例,再将原对象的属性值赋给新实例来实现深度复制。
这种方法的优点是可以避免在每个对象类中都实现复制方法,缺点是需要处理较多的Java 类型。
下面我们通过一个实例来说明使用递归和反射实现深度复制的方法。
实例:假设我们有一个对象 A,其中包含一个对象 B 的引用。
```javaclass A {int x;B b;}class B {int y;}```使用递归实现深度复制:```javapublic class DeepCopy {public static void main(String[] args) {A a = new A();a.x = 1;a.b = new B();a.b.y = 2;A aCopy = deepCopy(a);System.out.println(aCopy.x + ", " + aCopy.b.y); }public static A deepCopy(A a) {A aCopy = new A();aCopy.x = a.x;aCopy.b = (B) deepCopy(a.b);return aCopy;}}```使用反射实现深度复制:```javaimport ng.reflect.Field;public class DeepCopy {public static void main(String[] args) {A a = new A();a.x = 1;a.b = new B();a.b.y = 2;A aCopy = deepCopy(a);System.out.println(aCopy.x + ", " + aCopy.b.y); }public static A deepCopy(A a) {A aCopy = (A) reflectiveCopy(a, A.class);return aCopy;}public static Object reflectiveCopy(Object obj, Class<?> clazz) {Object copy = null;try {copy = clazz.newInstance();Field[] fields = clazz.getDeclaredFields();for (Field field : fields) {field.setAccessible(true);field.set(copy, field.get(obj));}} catch (Exception e) {e.printStackTrace();}return copy;}}```以上代码演示了如何使用递归和反射实现深度复制。
⼀⽂搞懂Java中深拷贝和浅拷贝的区别Java深拷贝和浅拷贝的区别浅拷贝被复制的对象的所有的变量都与原对象有相同的值,⽽所有的引⽤对象仍然指向原来的对象。
换⾔之,浅拷贝只是复制所考虑的对象,不复制引⽤对象。
1class Experience {2private String skill;3public void setSkill(String skill){4this.skill = skill;5 }6public void setExperience(String skill){7this.skill = skill;8 }910 @Override11public String toString() {12return skill;13 }14 }1516public class CloneTest implements Cloneable{1718private int age ;19private Experience experience;2021public CloneTest(){22this.age = 10;23this.experience = new Experience();24 }25public Experience getExperience() {26return experience;27 }28public void setExperience(String skill){29 experience.setExperience(skill);30 }31public void show(){32 System.out.println(experience.toString());33 }34public int getAge() {35return age;36 }37 @Override38protected Object clone() throws CloneNotSupportedException {39return (CloneTest) super.clone();40 }41 }42//测试类43class MianTest{4445public static void main(String[] args) throws CloneNotSupportedException {46 CloneTest test = new CloneTest();47 test.setExperience("我是⼩明,我精通Java,C++的复制粘贴");48 test.show();49 CloneTest cloneTest = (CloneTest) test.clone();50 cloneTest.show();51 cloneTest.setExperience("我是⼩明的副本,我精通Java,C++");52 cloneTest.show();53 test.show();54 System.out.println(cloneTest.getAge());55 }56 }输出的结果:我是⼩明,我精通Java,C++的复制粘贴我是⼩明,我精通Java,C++的复制粘贴我是⼩明的副本,我精通Java,C++我是⼩明的副本,我精通Java,C++10从结果中不难看出,拷贝的副本改变了Experience的skill属性,原类中的skill属性打印出来也是修改后的结果,说明引⽤类型的拷贝没有将对象拷贝,引⽤的指向还是原类中的指向深拷贝除了被复制的对象的所有变量都有原来对象的值之外,还把引⽤对象也指向了被复制的新对象1class Experience implements Cloneable{2private String skill;3public void setSkill(String skill){4this.skill = skill;5 }6public void setExperience(String skill){7this.skill = skill;8 }910 @Override11public String toString() {12return skill;13 }1415 @Override16protected Object clone() throws CloneNotSupportedException {17return super.clone();18 }19 }2021public class CloneTest implements Cloneable{2223private int age ;24private Experience experience;2526public CloneTest(){27this.age = 10;28this.experience = new Experience();29 }30public Experience getExperience() {31return experience;32 }33public void setExperience(String skill){34 experience.setExperience(skill);35 }36public void show(){37 System.out.println(experience.toString());38 }39public int getAge() {40return age;41 }42 @Override43protected Object clone() throws CloneNotSupportedException {44 CloneTest o = (CloneTest) super.clone();45 o.experience = (Experience) o.getExperience().clone();46return o;47 }48 }49class MianTest{5051public static void main(String[] args) throws CloneNotSupportedException {52 CloneTest test = new CloneTest();53 test.setExperience("我是⼩明,我精通Java,C++的复制粘贴");54 test.show();55 CloneTest cloneTest = (CloneTest) test.clone();56 cloneTest.show();57 cloneTest.setExperience("我是⼩明的副本,我精通Java,C++");58 cloneTest.show();59 test.show();60 System.out.println(cloneTest.getAge());61 }62 }输出的结果:我是⼩明,我精通Java,C++的复制粘贴我是⼩明,我精通Java,C++的复制粘贴我是⼩明的副本,我精通Java,C++我是⼩明,我精通Java,C++的复制粘贴10可以看出和第⼀次的结果不同了。
java对象的克隆(浅克隆和深克隆)java 对象的克隆⼀、对象的浅克隆(1)需要克隆类需要重写Object类的clone⽅法,并且实现Cloneable接⼝(标识接⼝,⽆需实现任何⽅法)(2)当需要克隆的对象中维护着另外⼀个引⽤对象,浅克隆不会克隆另外⼀个引⽤对下,⽽是直接复制维护的另外⼀个引⽤对象的地址。
(3)对象的浅克隆也不会调⽤到构造⽅法。
以下为对象的浅克隆的⼀个例⼦:package com.clone;import java.io.Serializable;/*** Description:* 实现了Cloneable接⼝,并重写Object类的clone⽅法。
** @author lee* */public class CloneDemo1 implements Cloneable,Serializable{//该克隆类封装的信息public int id;public String name;public Address address;/*** Desciption:* 默认构造器** */public CloneDemo1(){}/*** Description:* 初始化id,name的构造器** @param id id* @param name 名字* @param address 地址* */public CloneDemo1(int id, String name, Address address){this.id=id;=name;this.address = address;}/*** Descriptin:* 重写Object类的clone⽅法。
* if the object's class does not support the Cloneable interface.* Subclasses that override the clone method can also throw this exception* to indicate that an instance cannot be cloned.** @throws CloneNotSupportedException* */@Overridepublic Object clone() throws CloneNotSupportedException{return super.clone();}/*** Description:* 重写toString⽅法** @return "id="+id+", name="+name* */@Overridepublic String toString(){return "id="+id+", name="+name+", address:"+address.getAddress();}/*** Description:* 主⽅法** */public static void main(String[] args) throws CloneNotSupportedException{CloneDemo1 c1 = new CloneDemo1(1,"c1",new Address("北京"));//c2 复制了c1的地址,并没有复制整个c1对象CloneDemo1 c2 = c1;//c3 对象的浅克隆,复制了整个对象CloneDemo1 c3 = (CloneDemo1)c1.clone();//当对象c1改变其name或者id的时候,c2也会⾃动改变。
Java中copy的用法在Java中,copy是一种常见的操作,用于将数据从一个位置复制到另一个位置。
它可以用于复制对象、数组、集合等不同类型的数据。
本文将全面介绍Java中copy的用法,并提供一些示例代码来帮助读者更好地理解。
1. 复制对象在Java中,要复制一个对象,可以使用两种方式:浅拷贝和深拷贝。
1.1 浅拷贝浅拷贝是指将对象的字段值复制到新对象中,但是如果字段是引用类型,那么只会复制引用而不会复制引用指向的对象。
这意味着新旧对象将共享同一个引用对象。
Java提供了Object类中的clone()方法来实现浅拷贝。
要使用该方法,需要实现Cloneable接口并重写clone()方法。
以下是一个示例代码:class Person implements Cloneable {private String name;private int age;// 构造方法和其他方法省略@Overridepublic Object clone() throws CloneNotSupportedException {return super.clone();}}public class Main {public static void main(String[] args) throws CloneNotSupportedException { Person person1 = new Person("Alice", 20);Person person2 = (Person) person1.clone();System.out.println(person1); // 输出:Person@hashcodeSystem.out.println(person2); // 输出:Person@hashcode}}在上面的代码中,Person类实现了Cloneable接口,并重写了clone()方法。
在Java中,深拷贝和浅拷贝是两种不同的对象复制方法。
下面分别介绍深拷贝和浅拷贝的方法:1. 浅拷贝(Shallow Copy):浅拷贝是指复制对象,但不复制对象内部的引用类型的数据。
新对象与原对象共享内部引用类型的数据。
在Java中,可以通过clone()方法和一些特定的构造函数实现浅拷贝。
#使用clone()方法:public class MyClass implements Cloneable {private int intValue;private String stringValue;public MyClass clone() throws CloneNotSupportedException {return (MyClass) super.clone();}}#使用构造函数:public class MyClass {private int intValue;private String stringValue;public MyClass(MyClass original) {this.intValue = original.intValue;this.stringValue = original.stringValue;}}2. 深拷贝(Deep Copy):深拷贝是指复制对象,同时递归复制对象内部的引用类型的数据,使得新对象和原对象的内部引用类型数据完全独立。
在Java中,可以通过序列化、自定义深拷贝方法或使用第三方库实现深拷贝。
#使用序列化(Serializable):import java.io.*;public class MyClass implements Serializable {private int intValue;private String stringValue;public MyClass deepCopy() throws IOException, ClassNotFoundException {// 序列化ByteArrayOutputStream bos = new ByteArrayOutputStream();ObjectOutputStream oos = new ObjectOutputStream(bos);oos.writeObject(this);// 反序列化ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());ObjectInputStream ois = new ObjectInputStream(bis);return (MyClass) ois.readObject();}}#使用第三方库(例如Apache Commons Lang):import ng3.SerializationUtils;public class MyClass {private int intValue;private String stringValue;public MyClass deepCopy() {return SerializationUtils.clone(this);}}上述示例中,使用clone()方法、构造函数、序列化和第三方库都可以实现深拷贝,具体选择取决于应用场景和性能要求。
Java中对象的浅拷贝与深拷贝
Java中的拷贝方式分为深拷贝和浅拷贝。
简单来说,深拷贝就是把一个对象中的所有值,如果被拷贝对象中有对其他对象的引用,那么这个引用指向的对象本身会被重新创建。
浅拷贝和深拷贝类似,但是如果被拷贝对象中有对其他对象的引用,只是这个引用会被拷贝,而不是这个被引用的对象。
说起来有点绕口,那么我们就看看下面的图解吧:
深拷贝:
浅拷贝:
来看下面这段代码:
重点在Person person2 = person1;这一句上,person1里面包括了一个对Car对象的引用,那么这句话是深拷贝还是浅拷贝呢?答案是什么都不是。
它只是一个简单的引用传递,执行完这句话以后,person1和person2都指向了同一个person对象,所以无论谁去改变对象,另一个引用再去调用该对象的值都会发生改变。
好吧,言归正传,下面来实现一个浅拷贝。
Car类不变,Person实现了Cloneable接口,然后重载了父类的clone方法,并且直接调用super.clone()方法来拷贝。
但是值得注意的是,父类的clone只是浅拷贝,所以才会有上述的输出结果。
那么,要想达到深拷贝,需要做些什么呢?其实答案已经很明显了,因为clone是浅拷贝,而Car中都是原始类型的变量,所以我们只需要让Car类也实现Cloneable接口,然后重载clone方法,然后回到Person类中,在clone的时候,加上car = car.clone()就行了。
Person类中的clone:
然后我们回到test类中,再去看执行结果:
但是,在一些java原生类中,并没有实现clone方法,这表明他们是不能被拷贝的。
这时,如果想要达到深度拷贝的目的,就需要这么做: car = new Car();然后把原来的car 中的值全部一一重新set到新的car对象中。
其实,除了上面这种方法之外,还有一种方法能达到深拷贝的效果,那就是使用序列化。
在这里,我们首先让Car类实现Serializable接口使其能够序列化,其次就可以使用java中的io来传输对象了。
序列化能够达到深拷贝目的的原因是,它首先将对象的整个对象树持久化,然后全部读出,每读出一次就得到一个全新的拷贝。
但是这样做的坏处也不少,首当其冲的就是效率问题,序列化的方式比起clone方法的方式要慢不少。
最后需要说的是,我们究竟什么时候用浅拷贝,什么时候用深拷贝呢?答案就是如果一个对象中只包含原始类型的变量,那么就使用浅拷贝,如果类中有对其他类的引用,但是其他类是imutable 的,仍然使用浅拷贝。
如果有对其他类的引用,而其他类是可被修改的,这就不得不深拷贝了。