Bean 属性拷贝工具类(支持集合之间的拷贝)

发布时间:2026/10/4 0:10:17
Bean 属性拷贝工具类(支持集合之间的拷贝) 原理底层使用反射调用 Getter/Setter支持 Lambda 表达式自定义过滤与转换内有缓存 Bean 的 getter/setter 方法提升反射性能能够有效的解决一个Bean有很多的属性赋值写出批量重复性的赋值语句package com.wei.jieshubar.util; import java.beans.Introspector; import java.lang.reflect.Method; import java.util.*; import java.util.concurrent.ConcurrentHashMap; import java.util.function.BiFunction; import java.util.function.Predicate; import java.util.stream.Collectors; /** * Bean 属性复制工具类支持集合之间的拷贝 * 底层使用反射调用 getter/setter支持 Lambda 表达式自定义过滤与转换 * * author weiwei * version 1.0.0 * since 2026-06-26 21 38 */ public class CopyUtil { // 拷贝并返回新对象 /** * 拷贝源对象属性到目标类型的全新实例并返回 * 自动调用无参构造创建目标对象 * * param source 源对象 * param targetClass 目标类型须有无参构造 * param T 目标类型 * return 填充好属性的目标类型新实例 */ public static T T copyToNew(Object source, ClassT targetClass) { return copyToNew(source, targetClass, null, null); } /** * 带忽略属性的拷贝并返回新对象 */ public static T T copyToNew(Object source, ClassT targetClass, String... ignoreProperties) { SetString ignoreSet ignoreProperties null ? new HashSet() : Arrays.stream(ignoreProperties).collect(Collectors.toSet()); return copyToNew(source, targetClass, property - !ignoreSet.contains(property), null); } /** * 带属性过滤的拷贝并返回新对象 */ public static T T copyToNew(Object source, ClassT targetClass, PredicateString propertyFilter) { return copyToNew(source, targetClass, propertyFilter, null); } /** * 带值转换的拷贝并返回新对象 */ public static T T copyToNew(Object source, ClassT targetClass, BiFunctionString, Object, Object converter) { return copyToNew(source, targetClass, null, converter); } /** * 拷贝并返回新对象完整参数版过滤 转换 * * param source 源对象 * param targetClass 目标类型须有无参构造 * param propertyFilter 属性名过滤null 表示全部复制 * param converter 值转换器null 表示直接复制 * param T 目标类型 * return 填充后的目标类型新实例 */ public static T T copyToNew(Object source, ClassT targetClass, PredicateString propertyFilter, BiFunctionString, Object, Object converter) { if (source null || targetClass null) { throw new IllegalArgumentException(Source and target class must not be null); } try { T target targetClass.getDeclaredConstructor().newInstance(); copyProperties(source, target, propertyFilter, converter); return target; } catch (Exception e) { throw new RuntimeException(Failed to copy properties to new instance of targetClass.getSimpleName(), e); } } /** * 缓存 Bean 的 getter/setter 方法提升反射性能 */ private static final MapClass?, MapString, Method GETTER_CACHE new ConcurrentHashMap(); private static final MapClass?, MapString, Method SETTER_CACHE new ConcurrentHashMap(); // 基础复制 /** * 复制所有同名字段属性名相同且类型兼容 */ public static void copyProperties(Object source, Object target) { copyProperties(source, target, null, null); } /** * 忽略指定属性进行复制 */ public static void copyProperties(Object source, Object target, String... ignoreProperties) { SetString ignoreSet ignoreProperties null ? new HashSet() : Arrays.stream(ignoreProperties).collect(Collectors.toSet()); copyProperties(source, target, property - !ignoreSet.contains(property), null); } // Lambda 增强 /** * 使用 Lambda 表达式过滤需要复制的属性 * param propertyFilter 属性名过滤器返回 true 表示需要复制 */ public static void copyProperties(Object source, Object target, PredicateString propertyFilter) { copyProperties(source, target, propertyFilter, null); } /** * 使用 Lambda 自定义属性值转换 * param converter 值转换器入参(属性名, 源属性值)返回转换后的值若返回 null 则不进行赋值 */ public static void copyProperties(Object source, Object target, BiFunctionString, Object, Object converter) { copyProperties(source, target, null, converter); } /** * 核心复制方法灵活组合过滤与转换 * param propertyFilter 属性过滤null 表示全部复制 * param converter 值转换null 表示直接复制入参属性名和原始值返回新值 */ public static void copyProperties(Object source, Object target, PredicateString propertyFilter, BiFunctionString, Object, Object converter) { if (source null || target null) { throw new IllegalArgumentException(Source and target must not be null); } MapString, Method sourceGetters getGetters(source.getClass()); MapString, Method targetSetters getSetters(target.getClass()); for (Map.EntryString, Method entry : sourceGetters.entrySet()) { String propertyName entry.getKey(); // 检查目标是否有对应 setter Method setter targetSetters.get(propertyName); if (setter null) continue; // Lambda 过滤 if (propertyFilter ! null !propertyFilter.test(propertyName)) continue; try { Object value entry.getValue().invoke(source); // Lambda 转换 if (converter ! null) { value converter.apply(propertyName, value); if (value null) continue; // 转换返回 null 代表跳过赋值 } // 类型兼容性简单校验实际生产可扩展 if (value ! null !setter.getParameterTypes()[0].isAssignableFrom(value.getClass())) { continue; // 类型不匹配则跳过 } setter.invoke(target, value); } catch (Exception e) { throw new RuntimeException(Failed to copy property propertyName , e); } } } // 反射工具方法 /** * 获取类的所有 getter 方法返回属性名 - Method 的映射 */ private static MapString, Method getGetters(Class? clazz) { return GETTER_CACHE.computeIfAbsent(clazz, k - { MapString, Method getters new ConcurrentHashMap(); for (Method method : clazz.getMethods()) { if (isGetter(method)) { String propertyName getPropertyName(method); getters.put(propertyName, method); } } return getters; }); } /** * 获取类的所有 setter 方法返回属性名 - Method 的映射 */ private static MapString, Method getSetters(Class? clazz) { return SETTER_CACHE.computeIfAbsent(clazz, k - { MapString, Method setters new ConcurrentHashMap(); for (Method method : clazz.getMethods()) { if (isSetter(method)) { String propertyName getPropertyName(method); setters.put(propertyName, method); } } return setters; }); } /** * 判断是否为 getter 方法 */ private static boolean isGetter(Method method) { String name method.getName(); return (name.startsWith(get) name.length() 3 method.getParameterCount() 0 !void.class.equals(method.getReturnType())) || (name.startsWith(is) name.length() 2 method.getParameterCount() 0 (boolean.class.equals(method.getReturnType()) || Boolean.class.equals(method.getReturnType()))); } /** * 判断是否为 setter 方法 */ private static boolean isSetter(Method method) { String name method.getName(); return name.startsWith(set) name.length() 3 method.getParameterCount() 1 void.class.equals(method.getReturnType()); } /** * 从 getter/setter 方法名提取属性名Java Bean 规范 */ private static String getPropertyName(Method method) { String name method.getName(); if (name.startsWith(is)) { return Introspector.decapitalize(name.substring(2)); } return Introspector.decapitalize(name.substring(3)); } // 集合拷贝 /** * 将源集合中的每个对象复制到目标类型的实例中并组装成集合返回 * param sourceList 源对象集合 * param targetClass 目标元素类型须有无参构造 * param S 源元素类型 * param T 目标元素类型 * return 目标对象集合ArrayList */ public static S, T ListT copyList(ListS sourceList, ClassT targetClass) { return copyList(sourceList, targetClass, null, null); } /** * 带忽略属性的集合拷贝 */ public static S, T ListT copyList(ListS sourceList, ClassT targetClass, String... ignoreProperties) { SetString ignoreSet ignoreProperties null ? new HashSet() : Arrays.stream(ignoreProperties).collect(Collectors.toSet()); return copyList(sourceList, targetClass, prop - !ignoreSet.contains(prop), null); } /** * 带过滤条件的集合拷贝 */ public static S, T ListT copyList(ListS sourceList, ClassT targetClass, PredicateString propertyFilter) { return copyList(sourceList, targetClass, propertyFilter, null); } /** * 带值转换的集合拷贝 */ public static S, T ListT copyList(ListS sourceList, ClassT targetClass, BiFunctionString, Object, Object converter) { return copyList(sourceList, targetClass, null, converter); } /** * 集合拷贝核心方法灵活组合过滤和转换 * param sourceList 源集合 * param targetClass 目标元素类型 * param propertyFilter 属性过滤null 则全复制 * param converter 值转换null 则直接复制 * param S 源元素类型 * param T 目标元素类型 * return 目标对象集合 */ public static S, T ListT copyList(ListS sourceList, ClassT targetClass, PredicateString propertyFilter, BiFunctionString, Object, Object converter) { if (sourceList null || targetClass null) { throw new IllegalArgumentException(Source list and target class must not be null); } ListT targetList new ArrayList(sourceList.size()); for (S source : sourceList) { try { T target targetClass.getDeclaredConstructor().newInstance(); copyProperties(source, target, propertyFilter, converter); targetList.add(target); } catch (Exception e) { throw new RuntimeException(Failed to copy element to targetClass.getSimpleName(), e); } } return targetList; } }

关于本文作者

来自尧图内容编辑团队

尧图内容编辑团队 内容团队

尧图内容编辑团队

本文由尧图网络内容编辑团队执笔。团队由资深项目经理、前端工程师与设计师组成,所有内容均来自亲手交付的真实项目,先讲清问题、再给出可落地的解法。尧图深耕北京网站建设十年,服务过京华建材集团、智造科技等各行业客户,把一线经验沉淀为可复用的行业观察。

  • 十年建站经验,覆盖建材、制造、服务、文创等
  • 项目经理把关选题与事实准确性
  • 工程师与设计师联合撰写专业细节
  • 统一编辑规范,保证文风与排版一致
  • 每月复盘转化数据,迭代选题方向

延伸阅读

相关资讯与近期热门内容

深度阅读推荐

建站决策前值得细读的三篇

网站改版的5个关键决策
2024-08-12

网站改版的5个关键决策

什么时候该改版、改到什么程度、如何避免流量掉光,京华建材集团改版复盘给出答案。

获取专属建站方案

看完文章,把您的行业与预算告诉我们,免费获取一份量身定制的官网建设方案与报价。

立即免费咨询