Java 对象属性拷贝总结
下文笔者讲述java中对象属性拷贝的简介说明,如下所示
可使用BeanUtils.copyProperties()方法
是一个集合的时候就不能这样直接赋值了
对象拷贝的简介说明
Java中 数据类型分为值类型(基本数据类型)和引用类型 值类型包括int、double、byte、boolean、char等简单数据类型 引用类型包括类、接口、数组等复杂类型
对象拷贝分为浅拷贝(浅克隆)与深拷贝(深克隆)
浅拷贝与深拷贝差异
创建一个新对象
然后将当前对象的非静态字段复制到该新对象
如果字段是值类型的,那么对该字段执行复制
如果该字段是引用类型的话,则复制引用但不复制引用的对象
因此,原始对象及其副本引用同一个对象
创建一个新对象,然后将当前对象的非静态字段复制到该新对象
无论该字段是值类型的还是引用类型,都复制独立的一份
当你修改其中一个对象的任何内容时,都不会影响另一个对象的内容
为什么需要对象拷贝
Entity对应的是持久层数据结构(一般是数据库表的映射模型); Model 对应的是业务层的数据结构; VO 就是Controller和客户端交互的数据结构
例: 数据库查询出来的用户信息(表的映射模型)是UserDO 但是我们需要传递给客户端的是UserVO 这时候就需要把UserDO实例的属性一个一个赋值到UserVO实例中
对象拷贝工具类: org.springframework.beans.BeanUtils org.springframework.cglib.beans.BeanCopier ma.glasnost.orika org.mapstruct(强烈推荐)
BeanUtils
Spring中BeanUtils 其中实现的方式很简单 就是对两个对象中相同名字的属性进行简单get/set 仅检查属性的可访问性
单个对象拷贝
我们把数据库查询出来的UserDO.java 拷贝到 UserVO.java可使用BeanUtils.copyProperties()方法
@Test
public void commonCopy() {
UserDO userDO = new UserDO(1L, "Java265", 22, 1);
UserVO userVO = new UserVO();
BeanUtils.copyProperties(userDO, userVO);
log.info("userVO:{}",userVO);
}
运行效果:
.... userVO:UserVO(userId=1, userName=Java265, age=22, sex=null)
集合拷贝
刚刚拷贝的是一个对象,但是有时候我们想拷贝一组UerDO.java是一个集合的时候就不能这样直接赋值了
@Test public void listCopyFalse() { List<UserDO> userDOList = new ArrayList(); userDOList.add(new UserDO(1L, "Java265", 22, 1)); userDOList.add(new UserDO(2L, "Java265--3", 23, 2)); List<UserVO> userVOList = new ArrayList(); BeanUtils.copyProperties(userDOList, userVOList); log.info("userVOList:{}",userVOList); } 运行以上代码,将输出以下信息---- .... userVOList:[]
暴力拷贝法
@Test
public void listCopyCommon() {
List<UserDO> userDOList = new ArrayList();
userDOList.add(new UserDO(1L, "Java265", 22, 1));
userDOList.add(new UserDO(2L, "Java265-3", 23, 2));
List<UserVO> userVOList = new ArrayList();
userDOList.forEach(userDO ->{
UserVO userVO = new UserVO();
BeanUtils.copyProperties(userDO, userVO);
userVOList.add(userVO);
});
log.info("userVOList:{}",userVOList);
}
优雅拷贝
使用JDK 8 的函数式接口封装org.springframework.beans.BeanUtils
定义一个函数式接口
函数式接口里是可以包含默认方法,这里我们定义默认回调方法。
@FunctionalInterface
public interface BeanUtilCopyCallBack <S, T> {
/**
* 定义默认回调方法
* @param t
* @param s
*/
void callBack(S t, T s);
}
封装一个工具类 BeanUtilCopy.java
public class BeanUtilCopy extends BeanUtils {
/**
* 集合数据的拷贝
* @param sources: 数据源类
* @param target: 目标类::new(eg: UserVO::new)
* @return
*/
public static <S, T> List<T> copyListProperties(List<S> sources, Supplier<T> target) {
return copyListProperties(sources, target, null);
}
/**
* 带回调函数的集合数据的拷贝(可自定义字段拷贝规则)
* @param sources: 数据源类
* @param target: 目标类::new(eg: UserVO::new)
* @param callBack: 回调函数
* @return
*/
public static <S, T> List<T> copyListProperties(List<S> sources, Supplier<T> target, BeanUtilCopyCallBack<S, T> callBack) {
List<T> list = new ArrayList<>(sources.size());
for (S source : sources) {
T t = target.get();
copyProperties(source, t);
list.add(t);
if (callBack != null) {
// 回调
callBack.callBack(source, t);
}
}
return list;
}
}
简单拷贝测试
@Test
public void listCopyUp() {
List<UserDO> userDOList = new ArrayList();
userDOList.add(new UserDO(1L, "Java265", 16, 1));
userDOList.add(new UserDO(2L, "Java265-2", 28, 2));
List<UserVO> userVOList = BeanUtilCopy.copyListProperties(userDOList, UserVO::new);
log.info("userVOList:{}",userVOList);
}
注意事项
UserDO.java 和UserVO.java 最后一个字段sex类型不一样,分别是:Integer/String
版权声明
本文仅代表作者观点,不代表本站立场。
本文系作者授权发表,未经许可,不得转载。


