当前位置: 首页 > 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.dtcms.com/a/302121.html

相关文章:

  • 墨者:SQL手工注入漏洞测试(MySQL数据库-字符型)
  • haproxy实列
  • 开源AI智能体-JoyAgent集成Deepseek
  • AI论文阅读方法+arixiv
  • 元宇宙工厂前端新形态:Three.js与WebGL实现3D产线交互的轻量化之路
  • 使用std::transform实现并发计算
  • Java 开发新人,入职后的环境搭建和配置
  • 安宝特方案丨AI算法能力开放平台:适用于人工装配质检、点检、实操培训
  • Netty中trySuccess和setSuccess的区别
  • python-内存管理
  • 【FAQ】MS Dynamics 365 Sales配置方法汇总
  • Linux中应用程序的安装于管理
  • Java面试宝典:Spring Boot
  • 基于BEKK-GARCH模型的参数估计、最大似然估计以及参数标准误估计的MATLAB实现
  • 【Linux学习】(12)环境变量
  • 自定义spring-boot-starter
  • STM32F4—电源管理器
  • 网络安全笔记
  • 图像处理第三篇:初级篇(续)—— 照明的理论知识
  • Springboot社区养老保险系统小程序
  • 基础算法思想——分治
  • 服务器防护教程 - 宝塔篇
  • 大模型应用开发1-认识大模型
  • 【Linux】编辑器vim和编译器gcc/g++
  • go‑cdc‑chunkers:用 CDC 实现智能分块 强力去重
  • mp快速入门
  • AI在编程、测试、数据分析等领域的前沿应用(技术报告)
  • 深度思考和搜索研究 最新的GSPO强化学习算法
  • 第六届金头脑杯夏季巅峰挑战:以智慧之名,点亮幼儿成长之路
  • RV1126B-P机器视觉应用AIoT及边缘计算算力达2.0支持 HDR 、 3DNR