在我们实际项目开发过程中,我们经常需要将不同的两个对象实例进行属性复制,从而基于源对象的属性信息进行后续操作,而不改变源对象的属性信息,比如DTO数据传输对象和数据对象DO,我们需要将DO对象进行属性复制到DTO,但是对象格式又不一样,所以我们需要编写映射代码将对象中的属性值从一种类型转换成另一种类型。
对象拷贝
在具体介绍两种 BeanUtils 之前,先来补充一些基础知识。它们两种工具本质上就是对象拷贝工具,而对象拷贝又分为深拷贝
和浅拷贝
,下面进行详细解释。
什么是浅拷贝和深拷贝
在Java中,除了 基本数据类型之外,还存在 类的实例对象这个引用数据类型,而一般使用 “=”号做赋值操作的时候,对于基本数据类型,实际上是拷贝的它的值,但是对于对象而言,其实赋值的只是这个对象的引用
,将原对象的引用传递过去,他们实际还是指向的同一个对象。而浅拷贝和深拷贝就是在这个基础上做的区分
如果在拷贝这个对象的时候,只对基本数据类型进行了拷贝,而对引用数据类型只是进行引用的传递,而没有真实的创建一个新的对象,则认为是浅拷贝
。反之,在对引用数据类型进行拷贝的时候,创建了一个新的对象,并且复制其内的成员变量,则认为是深拷贝
。
简单来说:
- 浅拷贝:对基本数据类型进行值传递,对引用数据类型进行引用传递般的拷贝,此为浅拷贝
- 深拷贝:对基本数据类型进行值传递,对引用数据类型,创建一个新的对象,并复制其内容,此为深拷贝
Apache 的 BeanUtils
例子:
import lombok.AllArgsConstructor;
import lombok.Data;
@Data
@AllArgsConstructor
public class PersonSource {
private Integer id;
private String username;
private String password;
private Integer age;
}
import lombok.Data;
@Data
public class PersonDest {
private Integer id;
private String username;
private Integer age;
}
public class TestApacheBeanUtils {
public static void main(String[] args) {
PersonSource personSource = new PersonSource(1, "gdsfs", "1234", 21);
PersonDest personDest = new PersonDest();
BeanUtils.copyProperties(personSource,personDest);
System.out.println("personDest:"+personDest);
}
}
for (OneSubject oneSubject : finalSubjectlist) {
OneSubject oneSubject1 = new OneSubject();
/*oneSubject1.setId(oneSubject.getId());
oneSubject1.setTitle(oneSubject.getTitle());*/
//按照上面的写法,如果一个实体类里面有很多字段的话,这样写的话很不方便,
// 所以下面用一个工具类的写法,意思是把oneSubject中的值get出来再set进去oneSubject1里面,跟上面的代码是一样的(效果一样)
BeanUtils.copyProperties(oneSubject,oneSubject1);
//最后把set出来的对象放在finalSubjectlist里面
finalSubjectlist.add(oneSubject1);
}
其中OneSubject实体类如下:
@Data
public class OneSubject implements Serializable {
private String id;
private String title;
//一个一级分类里面有多个二级分类
private List<TwoSubject> children = new ArrayList<>();
}