Java 深copy 浅copy 引用copy
程序员文章站
2022-06-03 14:22:06
...
大家好,我是烤鸭:
今天分享一下浅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() {
}
@Test
public 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;
}
@Override
public String toString() {
return "Person{" +
"id='" + id + '\'' +
", name='" + name + '\'' +
", sex='" + sex + '\'' +
'}';
}
@Override
public 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;
}
@Override
public String toString() {
return "Person{" +
"id='" + id + '\'' +
", name='" + name + '\'' +
", sex='" + sex + '\'' +
", man=" + man +
'}';
}
@Override
public 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;
}
@Override
public String toString() {
return "Man{" +
"name='" + name + '\'' +
", age='" + age + '\'' +
'}';
}
}
/**
* 浅复制
* @throws IOException
* @throws ClassNotFoundException
*/
@Test
public 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;
}
@Override
public String toString() {
return "Man{" +
"name='" + name + '\'' +
", age='" + age + '\'' +
'}';
}
@Override
protected 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
*/
@Test
public 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);
}
如图: