java的深浅拷贝_Java 深浅拷贝

Java 深拷贝和浅拷贝

在浅拷贝中,如果原型对象的成员变量是基本类型时,将复制一份给克隆对象;如果原型对象的成员变量是引用类型,则将引用对象的地址复制一份给克隆对象,也就是说原型对象和克隆对象的成员变量指向相同的内存地址。

对应的深拷贝,如果时成员变量为引用对象也复制一份给复制对象。

实现

1、新建一个 Person 和 PersonId 类

public class Person implementsCloneable {privateString name;private intage;privatePersonId personId;public Person(String name, int age, intid) {this.name =name;this.age =age;this.personId = newPersonId(id);

}public void setId(intid) {

personId.setId(id);

}public void setAge(intage) {this.age =age;

}public Person clone() throwsCloneNotSupportedException {

Person cloned= (Person)super.clone();returncloned;

}

@OverridepublicString toString() {return "Person{" +

"name='" + name + '\'' +

", age=" + age +

", personId=" + personId +

'}';

}

}

classPersonId{private intid;public PersonId(intid) {this.id =id;

}public intgetId() {returnid;

}public void setId(intid) {this.id =id;

}

@OverridepublicString toString() {return "PersonId{" +

"id=" + id +

'}';

}

}

2、使用 CloneDemo 类来测试浅拷贝

public classCloneDemo {public static void main(String[] args) throwsCloneNotSupportedException {

Person person= new Person("zhangsan",20,123);

Person cloned=person.clone();

System.out.println("original: "+person);

System.out.println("cloned: "+cloned);

System.out.println("Modify Age and Id: ");

cloned.setAge(55);

cloned.setId(234);

System.out.println("original: "+person);

System.out.println("cloned: "+cloned);

}

}

3、输出

可以看到我们修改了拷贝对象的年龄和ID,原始对象的年龄还是20,原始对象的ID却变成了我们修改后的值,我们并没有对原始对象的ID进行修改,这里说明浅拷贝对于对象仅仅是拷贝了一个对象的引用而已。

4、接下来我们修改 Person 类的 clone() 方法,实现深拷贝。

public Person clone() throwsCloneNotSupportedException {

Person cloned= (Person)super.clone();

cloned.personId=personId.clone();returncloned;

}

5、为了拷贝PersonId 的对象我们需要PersonId 类实现 Cloneable 接口

class PersonId implementsCloneable{private intid;public PersonId(intid) {this.id =id;

}public intgetId() {returnid;

}public void setId(intid) {this.id =id;

}

@OverridepublicString toString() {return "PersonId{" +

"id=" + id +

'}';

}public PersonId clone() throwsCloneNotSupportedException {return (PersonId)super.clone();

}

}

6、再次运行 CloneDemo 输出

可以看到 原始对象的ID 值没有被修改。

7、使用序列化实现深拷贝

import java.io.*;public class Person implementsCloneable, Serializable {privateString name;private intage;privatePersonId personId;public Person(String name, int age, intid) {this.name =name;this.age =age;this.personId = newPersonId(id);

}public void setId(intid) {

personId.setId(id);

}public void setAge(intage) {this.age =age;

}public Person clone() throwsCloneNotSupportedException {try{

ByteArrayOutputStream bout= newByteArrayOutputStream();try(ObjectOutputStream out = newObjectOutputStream(bout)) {

out.writeObject(this);

}try(InputStream bin = newByteArrayInputStream(bout.toByteArray())){

ObjectInputStream in= newObjectInputStream(bin);return(Person)in.readObject();

}

}catch (IOException |ClassNotFoundException e) {

CloneNotSupportedException e2= newCloneNotSupportedException();

e2.initCause(e);throwe2;

}

}

@OverridepublicString toString() {return "Person{" +

"name='" + name + '\'' +

", age=" + age +

", personId=" + personId +

'}';

}

}class PersonId implementsCloneable,Serializable{private intid;public PersonId(intid) {this.id =id;

}public intgetId() {returnid;

}public void setId(intid) {this.id =id;

}

@OverridepublicString toString() {return "PersonId{" +

"id=" + id +

'}';

}public PersonId clone() throwsCloneNotSupportedException {return (PersonId)super.clone();

}

}

所有写入流的对象都要实现 Serializable 接口。将 Person 对象写入流中然后再从流中读取出来实现深拷贝。

输出:

总结

若要实现深拷贝,如果对象中引用了其他对象,必须将引用的对象也克隆。

你可能感兴趣的:(java的深浅拷贝)