Java 对象属性拷贝总结

书欣 Java经验 发布时间:2022-08-08 17:58:26 阅读数:20116 1
下文笔者讲述java中对象属性拷贝的简介说明,如下所示

对象拷贝的简介说明

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
版权声明

本文仅代表作者观点,不代表本站立场。
本文系作者授权发表,未经许可,不得转载。

本文链接: https://www.Java265.com/JavaJingYan/202208/16599527334192.html

最近发表

热门文章

好文推荐

Java265.com

https://www.java265.com

站长统计|粤ICP备14097017号-3

Powered By Java265.com信息维护小组

使用手机扫描二维码

关注我们看更多资讯

java爱好者