当前位置: 首页 > news >正文

实用工具类分享:BeanCopyUtils 实现对象深浅拷贝高效处理

在日常开发中,对象拷贝是高频操作——从 DTO 与 Entity 转换,到集合数据复制,都离不开可靠的拷贝工具。今天分享一个基于 Spring 和 Java 原生 API 实现的 BeanCopyUtils,涵盖单对象/集合的浅拷贝与深拷贝,附使用场景与注意事项。

一、工具类核心功能与代码解析

先看完整代码(已添加关键注释):


import com.google.common.collect.Lists;
import lombok.SneakyThrows;
import org.springframework.beans.BeanUtils;import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.Collection;
import java.util.List;
import java.util.Objects;/*** Java实例拷贝工具类:支持浅拷贝(单对象/集合)、深拷贝(单对象/集合)*/
public class BeanCopyUtils {/*** 浅拷贝单个对象:基于Spring BeanUtils实现* @param source 源对象(非null)* @param targetCls 目标对象Class* @return 拷贝后的目标对象*/@SneakyThrows // Lombok注解:简化异常处理(实际开发可根据需求调整)public static <S, T> T copy(S source, Class<T> targetCls) {if (Objects.isNull(source)) {return null; // 源对象为null时直接返回null,避免空指针}T target = targetCls.newInstance(); // 反射创建目标对象实例BeanUtils.copyProperties(source, target); // 核心:复制属性(浅拷贝)return target;}/*** 浅拷贝集合:批量处理对象拷贝* @param source 源对象集合(非null)* @param targetCls 目标对象Class* @return 拷贝后的目标对象集合*/@SneakyThrowspublic static <S, T> List<T> copy(Collection<S> source, Class<T> targetCls) {List<T> list = Lists.newArrayList(); // 基于Guava创建集合(高效初始化)source.forEach(s -> list.add(copy(s, targetCls))); // 循环调用单对象拷贝return list;}/*** 深拷贝单个对象:基于对象序列化实现* @param source 源对象(需实现Serializable接口)* @return 完全独立的拷贝对象*/@SneakyThrows@SuppressWarnings("unchecked")public static <S, T> T deepCopy(S source) {if (Objects.isNull(source)) {return null;}T target;// 序列化:将对象写入字节流try (ByteArrayOutputStream bos = new ByteArrayOutputStream();ObjectOutputStream oos = new ObjectOutputStream(bos)) {oos.writeObject(source);// 反序列化:从字节流重建对象(新内存地址)ByteArrayInputStream byteIn = new ByteArrayInputStream(bos.toByteArray());ObjectInputStream in = new ObjectInputStream(byteIn);target = (T) in.readObject();}return target;}/*** 深拷贝集合:批量处理深拷贝* @param source 源对象集合(元素需实现Serializable)* @return 完全独立的拷贝集合*/@SneakyThrows@SuppressWarnings("unchecked")public static <S, T> List<T> deepCopy(Collection<S> source) {if (Objects.isNull(source)) {return null;}List<T> target;// 同单对象深拷贝逻辑,直接序列化整个集合try (ByteArrayOutputStream bos = new ByteArrayOutputStream();ObjectOutputStream oos = new ObjectOutputStream(bos)) {oos.writeObject(source);ByteArrayInputStream byteIn = new ByteArrayInputStream(bos.toByteArray());ObjectInputStream in = new ObjectInputStream(byteIn);target = (List<T>) in.readObject();}return target;}
}

二、核心原理与适用场景

1. 浅拷贝(copy 方法)

  • 原理:基于 Spring BeanUtils.copyProperties,仅复制对象的“表层属性”(基本类型直接复制,引用类型复制地址)。
  • 优势:速度快、无额外依赖(仅需Spring核心包)。
  • 适用场景
    • DTO与Entity的简单转换(如接口入参→数据库实体);
    • 临时对象复制(无需修改引用类型属性时)。
  • 注意:若源对象包含引用类型(如List、自定义对象),修改拷贝对象的引用属性会影响源对象。

2. 深拷贝(deepCopy 方法)

  • 原理:通过“对象序列化→反序列化”,将对象转化为字节流再重建,完全生成新对象(内存地址独立)。
  • 优势:拷贝彻底,源对象与拷贝对象完全隔离。
  • 适用场景
    • 需要修改拷贝对象的引用属性(如处理集合内元素,不影响原集合);
    • 复杂对象复制(含多层嵌套引用类型)。
  • 注意:源对象及内部所有引用类型必须实现 Serializable 接口,否则会抛出序列化异常。

三、使用示例与效果对比

1. 浅拷贝示例

// 定义实体类
class User {private String name;private List<String> hobbies; // 引用类型// getter/setter
}// 使用工具类
User source = new User();
source.setName("张三");
source.setHobbies(Arrays.asList("篮球", "游戏"));// 浅拷贝
User copy = BeanCopyUtils.copy(source, User.class);
copy.getHobbies().add("读书"); // 修改拷贝对象的引用属性// 结果:source的hobbies也会新增"读书"(引用相同)
System.out.println(source.getHobbies().size()); // 输出:3

2. 深拷贝示例

// 注意:User及内部引用类型需实现Serializable
class User implements Serializable {private String name;private List<String> hobbies; // List已实现Serializable// getter/setter
}// 使用工具类
User source = new User();
source.setName("张三");
source.setHobbies(Arrays.asList("篮球", "游戏"));// 深拷贝
User deepCopy = BeanCopyUtils.deepCopy(source);
deepCopy.getHobbies().add("读书");// 结果:源对象不受影响
System.out.println(source.getHobbies().size()); // 输出:2
System.out.println(deepCopy.getHobbies().size()); // 输出:3

四、性能对比与优化建议

拷贝类型速度内存开销适用对象
浅拷贝简单对象、无引用修改需求
深拷贝较慢大(需序列化)复杂对象、需完全隔离

优化建议:

  1. 优先使用浅拷贝(性能更优),仅在必要时用深拷贝;
  2. 深拷贝可考虑引入 Apache Commons LangSerializationUtils 进一步简化;
  3. 对超大集合拷贝,建议分批处理(避免一次性占用过多内存)。

五、总结

BeanCopyUtils 封装了深浅拷贝的核心逻辑,通过简洁的API解决日常开发中的对象复制问题。使用时需根据场景选择拷贝方式:浅拷贝适合简单转换,深拷贝适合复杂隔离场景。记住两者的核心区别(引用类型是否共享),可有效避免因对象引用导致的意外数据修改问题。也可以根据实际需求扩展(如添加字段过滤、自定义转换器等)。
如果觉得有用,欢迎点赞收藏。

http://www.lryc.cn/news/602501.html

相关文章:

  • 对于ui=f(state)的理解(react)
  • 基于springboot的大创管理系统(源码+论文+开题报告)
  • 【React Context API 优化与性能实践指南】
  • 【前端】React 与 Vue:前端两大框架的全方位对比解析
  • JVM 内存模型深度解析:原子性、可见性与有序性的实现
  • 如何给电脑换个ip地址?电脑换ip几种方法
  • 测试平台开发:自动化测试平台----需求分析
  • fmriprep安装与试用_附ubuntu分区大小调整
  • NAT地址转换,静态NAT,高级NAT,NAPT,easy IP
  • JAVA_EIGHTEEN_特殊文件
  • 使用 nvm (Node Version Manager) 来管理多个 Node.js 版本,并自由切换
  • 从文件到文件描述符:理解程序与文件的交互本质
  • 前端可智能识别的搜索组件 SearchBox 使用详解!
  • DOM编程:table表格开发常用属性和操作汇总
  • it is not annotated with @ClientEndpoint“
  • nginx日志分割
  • Webhook技术深度解析:从原理到实现全指南
  • Cloudflare CDN 中设置地域限制并返回特定界面
  • DNF 与 YUM 的区别详解:从 CentOS 7 到 CentOS 9 的演进
  • nuttx串口驱动框架设计
  • HCIP笔记(第一、二章)
  • 设计模式(十六)行为型:解释器模式详解
  • 自定义View学习记录 plinko游戏View
  • 6、CentOS 9 安装 Docker
  • 状态反馈极点配置
  • 第三阶段—8天Python从入门到精通【itheima】-139节(pysqark实战-前言介绍)
  • mac电脑如何关闭防火墙
  • 本地大语言模型部署指南
  • 分布式渲染效能探析:关键网络性能要素
  • 前端基础之《Vue(25)—Vue3简介》