大家好,我是烤鸭:
今天分享一下浅copy和深copy。
1. 深copy
什么是深copy,只复制原对象属性值,不管地址。
说一下业务场景:
如果我想创建一个对象,只是对原对象的某个属性值改变。普通的做法就是new 一个对象,然后setXXX,如果属性特别多的话不方便,这时候就是需要深copy。复制出来的对象属于不同的地址,改变复制对象的属性值不会影响原对象。
TestClone.java:
package com.xxx.xxx.utils;import org.junit.Test;import java.io.Serializable;/*** Created by on 2018/7/23*/
public class TestClone {public TestClone() {}@Testpublic void testDeepCopy(){Person person1 = new Person();person1.id = "id1";person1.name = "name1";person1.sex = "sex1";System.out.println("复制前person:"+person1);Person clone = CloneUtils.clone(person1);System.out.println("这是深copy后的对象:"+clone);System.out.println("=========改变深copy后的对象属性=====================");clone.id = "id2";clone.name = "name2";clone.sex = "sex2";System.out.println("copy的对象:"+clone);System.out.println("复制后person:"+person1);}}
class Person implements Serializable,Cloneable{String id;String name;String sex;public String getId() {return id;}public void setId(String id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}public String getSex() {return sex;}public void setSex(String sex) {this.sex = sex;}@Overridepublic String toString() {return "Person{" +"id='" + id + '\'' +", name='" + name + '\'' +", sex='" + sex + '\'' +'}';}@Overridepublic Person clone() {Person person = null;try {person = (Person) super.clone();} catch (CloneNotSupportedException ignored) {System.out.println(ignored.getMessage());}return person;}
}
CloneUtils.java:
package com.xxx.xxx.utils;import java.io.*;public class CloneUtils {@SuppressWarnings("unchecked")public static <T extends Serializable> T clone(T obj){T cloneObj = null;try {//写入字节流ByteArrayOutputStream out = new ByteArrayOutputStream();ObjectOutputStream obs = new ObjectOutputStream(out);obs.writeObject(obj);obs.close();//分配内存,写入原始对象,生成新对象ByteArrayInputStream ios = new ByteArrayInputStream(out.toByteArray());ObjectInputStream ois = new ObjectInputStream(ios);//返回生成的新对象cloneObj = (T) ois.readObject();ois.close();} catch (Exception e) {e.printStackTrace();}return cloneObj;}
}
结果如图:
2. 浅copy
与深copy相对应,浅copy就是复制的对象指向了原对象的地址值。如果复制的对象属性值改变,原对象也会随之改变。
如果是单个对象的话,用引用copy吧。
如果是对象中还有属性是对象的话。
Person.java 和 Man.java
class Person implements Cloneable, Serializable {String id;String name;String sex;Man man;public String getId() {return id;}public void setId(String id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}public String getSex() {return sex;}public void setSex(String sex) {this.sex = sex;}public Man getMan() {return man;}public void setMan(Man man) {this.man = man;}@Overridepublic String toString() {return "Person{" +"id='" + id + '\'' +", name='" + name + '\'' +", sex='" + sex + '\'' +", man=" + man +'}';}@Overridepublic Person clone() {Person person = null;try {person = (Person) super.clone();} catch (CloneNotSupportedException ignored) {System.out.println(ignored.getMessage());}return person;}
}
class Man{String name;String age;public String getName() {return name;}public void setName(String name) {this.name = name;}public String getAge() {return age;}public void setAge(String age) {this.age = age;}@Overridepublic String toString() {return "Man{" +"name='" + name + '\'' +", age='" + age + '\'' +'}';}
}
/*** 浅复制* @throws IOException* @throws ClassNotFoundException*/@Testpublic void testShallowCopy() throws IOException, ClassNotFoundException {Person person1 = new Person();Man man = new Man();man.name = "man1";man.age = "age1";person1.id = "id1";person1.name = "name1";person1.sex = "sex1";person1.man = man;System.out.println("复制前person:"+person1);Person clone = person1.clone();System.out.println("这是浅copy后的对象:"+clone);System.out.println("=========改变浅copy后的对象属性=====================");clone.id = "id2";clone.name = "name2";clone.sex = "sex2";clone.man.name = "man2";clone.man.age = "age2";System.out.println("copy的对象:"+clone);System.out.println("复制后person:"+person1);}
如图:
可以看出,改变了man的属性,原对象中的man属性值也改变了。这就是浅copy。
如果不想这样的话,就把man也clone。
man实现clone接口,重写clone方法:
class Man implements Cloneable{String name;String age;public String getName() {return name;}public void setName(String name) {this.name = name;}public String getAge() {return age;}public void setAge(String age) {this.age = age;}@Overridepublic String toString() {return "Man{" +"name='" + name + '\'' +", age='" + age + '\'' +'}';}@Overrideprotected Object clone() throws CloneNotSupportedException {return super.clone();}
}
修改copy方法:
Man man2 = (Man) person1.man.clone();man2.name = "man2";man2.age = "age2";clone.man = man2;
如图:
3. 引用copy
/*** 引用复制* @throws IOException* @throws ClassNotFoundException*/@Testpublic void testQuoteCopy() throws IOException, ClassNotFoundException {Person person1 = new Person();person1.id = "id1";person1.name = "name1";person1.sex = "sex1";System.out.println("复制前person:"+person1);Person clone = person1;System.out.println("这是引用copy后的对象:"+clone);System.out.println("=========改变引用copy后的对象属性=====================");clone.id = "id2";clone.name = "name2";clone.sex = "sex2";System.out.println("copy的对象:"+clone);System.out.println("复制后person:"+person1);}
如图: