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
版权声明
本文仅代表作者观点,不代表本站立场。
本文系作者授权发表,未经许可,不得转载。