一、为什么需要优化传统序列化深复制?
二、ListCopyUtils 核心实现与优化点
1. 核心代码
import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.*; import java.util.ArrayList; import java.util.Collections; import java.util.List;/*** 列表深复制工具类:基于序列化,兼顾性能、安全与易用性*/ public class ListCopyUtils {private static final Logger log = LoggerFactory.getLogger(ListCopyUtils.class);// 不可变空列表常量:避免重复创建空集合,减少内存浪费private static final List<?> EMPTY_IMMUTABLE_LIST = Collections.emptyList();/*** 标准深复制(抛出异常,适合需精细处理失败场景)* @param sourceList 源列表(元素必须实现Serializable)* @param elementType 元素Class(用于类型校验)* @param <T> 元素类型(需实现Serializable)* @return 深复制后的新列表* @throws IOException 序列化/反序列化失败时抛出*/public static <T extends Serializable> List<T> deepCopyList(List<T> sourceList, Class<T> elementType) throws IOException {// 空列表快速返回:避免无效IO操作if (sourceList == null || sourceList.isEmpty()) {return (List<T>) EMPTY_IMMUTABLE_LIST;}// try-with-resources自动关闭流:杜绝资源泄漏try (ByteArrayOutputStream bos = new ByteArrayOutputStream();ObjectOutputStream oos = new ObjectOutputStream(bos)) {// 序列化:强制刷新缓冲区,确保数据完整 oos.writeObject(sourceList);oos.flush();// 反序列化:二次校验类型,提前暴露问题try (ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());ObjectInputStream ois = new ObjectInputStream(bis)) {Object deserialized = ois.readObject();// 一级校验:是否为List类型if (!(deserialized instanceof List)) {throw new ClassCastException("反序列化结果非List类型");}List<?> rawList = (List<?>) deserialized;// 预初始化容量:避免动态扩容,提升性能List<T> resultList = new ArrayList<>(rawList.size());// 二级校验:逐个元素类型匹配(确保泛型安全)for (Object element : rawList) {if (element == null) {resultList.add(null);continue;}if (!elementType.isInstance(element)) {throw new ClassCastException(String.format("元素类型不匹配:期望%s,实际%s",elementType.getName(), element.getClass().getName()));}resultList.add(elementType.cast(element));}return resultList;} catch (ClassNotFoundException e) {log.error("反序列化失败:类定义缺失", e);throw new IOException("深复制失败:类版本不兼容", e);}}}/*** 安全深复制(不抛受检异常,适合快速使用场景)* @param sourceList 源列表* @param elementType 元素Class* @param <T> 元素类型* @return 复制结果(失败时返回空列表,避免NPE)*/public static <T extends Serializable> List<T> safeDeepCopyList(List<T> sourceList, Class<T> elementType) {try {return deepCopyList(sourceList, elementType);} catch (IOException e) {log.error("列表深复制失败", e);return new ArrayList<>(0); // 返回空列表而非null,降低调用方风险 }} }
2. 关键优化点解析
三、使用示例
1. 依赖前提
列表元素必须实现Serializable
接口(序列化深复制的基础要求),示例元素类:
// 实现Serializable接口的用户类 public class User implements Serializable {private String name;private Integer age;// 构造器、getter、setter省略 }
2. 标准使用(精细处理失败场景)
// 源列表数据 List<User> originalList = new ArrayList<>(); originalList.add(new User("张三", 25)); originalList.add(new User("李四", 30));try {// 深复制(需处理IOException)List<User> copyList = ListCopyUtils.deepCopyList(originalList, User.class);// 修改副本,原列表不受影响copyList.get(0).setName("张三-副本");System.out.println("原列表第一个元素:" + originalList.get(0).getName()); // 输出“张三” } catch (IOException e) {// 处理复制失败(如重试、提示用户)System.err.println("复制失败:" + e.getMessage()); }
3. 简化使用(快速集成场景)
// 无需处理异常,失败时返回空列表 List<User> safeCopyList = ListCopyUtils.safeDeepCopyList(originalList, User.class); if (safeCopyList.isEmpty()) {System.out.println("复制失败或源列表为空"); } else {// 业务处理 }