1.二者的区别
名称 | 本质 |
---|---|
浅拷贝 | 在拷贝一个对象时,对对象的基本数据类型的成员变量进行拷贝,但对引用类型的成员变量只进行引用的传递,并没有创建一个新的对象,当对引用类型的内容修改会影响被拷贝的对象。 |
深拷贝 | 在拷贝一个对象时,除了对基本数据类型的成员变量进行拷贝,对引用类型的成员变量进行拷贝时,创建一个新的对象来保存引用类型的成员变量。 |
2.深拷贝和浅拷贝的实现
下面根据两个实体类来谈一谈浅拷贝和深拷贝的实现
package domain;
import java.io.Serializable;
/**
* @author Mr.MC
*/
public class People implements Serializable {
private String name;
private Character sex;
private Animal animal;
public People() {
}
public People(String name, Character sex, Animal animal) {
this.name = name;
this.sex = sex;
this.animal = animal;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Character getSex() {
return sex;
}
public void setSex(Character sex) {
this.sex = sex;
}
public Animal getAnimal() {
return animal;
}
public void setAnimal(Animal animal) {
this.animal = animal;
}
@Override
public String toString() {
return "People{" +
"name='" + name + '\'' +
", sex=" + sex +
", animal=" + animal +
'}';
}
}
package domain;
import java.io.Serializable;
/**
* @author Mr.MC
*/
public class Animal implements Serializable {
private String name;
private String color;
public Animal() {
}
public Animal(String name, String color) {
this.name = name;
this.color = color;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
@Override
public String toString() {
return "Animal{" +
"name='" + name + '\'' +
", color='" + color + '\'' +
'}';
}
}
2.1.浅拷贝的实现
这里笔者只提一下BeanUtils这个类
原因是在这里栽了两个坑
其一是一直以为BeanUtils这个类是深拷贝,后来发现只是通过反射实现了浅拷贝。
/**
* org.apache.commons.beanutils包下和org.springframework.beans包下的
* BeanUtils的复制都是浅拷贝
*
* @throws InvocationTargetException
* @throws IllegalAccessException
*/
@Test
public void test01() throws InvocationTargetException, IllegalAccessException {
People sourcePeople = new People("张三", '男', new Animal("哈士奇", "黑白"));
People targetPeople = new People();
BeanUtils.copyProperties(targetPeople, sourcePeople);
// targetPeople.setAnimal(new Animal("金毛", "橘黄"));
targetPeople.getAnimal().setName("金毛");
targetPeople.getAnimal().setColor("橘黄");
System.out.println(sourcePeople);
System.out.println(targetPeople);
}
结果如下
断点中也可以看出两个People对象中的成员变量Animal实际上指向了同一个对象
其二是Spring和Apache都有BeanUtils这个工具类,但是参数略有不同,一定要注意自己到底引用的是哪个包!
包 | 方法 | 区别 |
---|---|---|
org.springframework.beans | public static void copyProperties(Object source, Object target) throws BeansException | 第一个参数是源对象,第二个参数是目标对象 |
org.apache.commons.beanutils | public static void copyProperties(Object dest, Object orig) throws IllegalAccessException, InvocationTargetException | 第一个参数是目标对象,第二个参数是源对象 |
2.2深拷贝的实现
目前笔者只尝试了两种工具类的实现方式
一种是org.apache.commons.lang3下的SerializationUtils工具类
/**
* lang3下的SerializationUtils的深拷贝
*/
@Test
public void test02() {
People sourcePeople = new People("张三", '男', new Animal("哈士奇", "黑白"));
People targetPeople = SerializationUtils.clone(sourcePeople);
sourcePeople.getAnimal().setName("金毛");
sourcePeople.getAnimal().setColor("橘黄");
System.out.println(sourcePeople);
System.out.println(targetPeople);
}
结果如下
断点中查看两个People对象的成员变量Animal实际上指向了不同对象
第二种是com.alibaba.fastjson工具类
@Test
public void test03() {
People sourcePeople = new People("张三", '男', new Animal("哈士奇", "黑白"));
String json = JSON.toJSONString(sourcePeople);
People targetPeople = JSON.parseObject(json, People.class);
sourcePeople.getAnimal().setName("金毛");
sourcePeople.getAnimal().setColor("橘黄");
System.out.println(sourcePeople);
System.out.println(targetPeople);
}
结果如下
断点中也是指向了不同对象