java如何拷贝复制对象和集合问题
作者:Yang疯狂打码中
这篇文章主要介绍了java如何拷贝复制对象和集合问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
在Java中常见的对象拷贝方式是使用cglib,Cglib的性能是目前公认最好的,用于解决Bean拷贝的性能问题
下面是以cglib封装的工具类实现对象和集合的拷贝
一、引入依赖
<dependency> <groupId>cglib</groupId> <artifactId>cglib</artifactId> <version>3.3.0</version> <scope>compile</scope> </dependency>
二、创建CglibUtil工具类
其中包含对象和集合的拷贝,还封装了Bean转Map的方法
import cn.hutool.core.lang.Assert; import cn.hutool.core.util.ReflectUtil; import net.sf.cglib.beans.BeanCopier; import net.sf.cglib.beans.BeanMap; import net.sf.cglib.core.Converter; import java.util.Collection; import java.util.List; import java.util.function.BiConsumer; import java.util.function.Supplier; import java.util.stream.Collectors; /** * @author YangBoss * @title: CglibUtil * @projectName frontop-ao * @description: CglibUtil工具类 * @date 2022/6/2 10:18 */ public class CglibUtil { /** * 拷贝Bean对象属性到目标类型<br> * 此方法通过指定目标类型自动创建之,然后拷贝属性 * * @param <T> 目标对象类型 * @param source 源bean对象 * @param targetClass 目标bean类,自动实例化此对象 * @return 目标对象 */ public static <T> T copy(Object source, Class<T> targetClass) { return copy(source, targetClass, null); } /** * 拷贝Bean对象属性<br> * 此方法通过指定目标类型自动创建之,然后拷贝属性 * * @param <T> 目标对象类型 * @param source 源bean对象 * @param targetClass 目标bean类,自动实例化此对象 * @param converter 转换器,无需可传{@code null} * @return 目标对象 */ public static <T> T copy(Object source, Class<T> targetClass, Converter converter) { final T target = ReflectUtil.newInstanceIfPossible(targetClass); copy(source, target, converter); return target; } /** * 拷贝Bean对象属性 * * @param source 源bean对象 * @param target 目标bean对象 */ public static void copy(Object source, Object target) { copy(source, target, null); } /** * 拷贝Bean对象属性 * * @param source 源bean对象 * @param target 目标beBeanCopierCachean对象 * @param converter 转换器,无需可传{@code null} */ public static void copy(Object source, Object target, Converter converter) { Assert.notNull(source, "Source bean must be not null."); Assert.notNull(target, "Target bean must be not null."); final Class<?> sourceClass = source.getClass(); final Class<?> targetClass = target.getClass(); boolean conIsNull = converter == null ? false : true; final BeanCopier beanCopier = BeanCopier.create(sourceClass, targetClass, conIsNull); beanCopier.copy(source, target, converter); } /** * 拷贝List Bean对象属性 * * @param <S> 源bean类型 * @param <T> 目标bean类型 * @param source 源bean对象list * @param target 目标bean对象 * @return 目标bean对象list */ public static <S, T> List<T> copyList(Collection<S> source, Supplier<T> target) { return copyList(source, target, null, null); } /** * 拷贝List Bean对象属性 * * @param source 源bean对象list * @param target 目标bean对象 * @param converter 转换器,无需可传{@code null} * @param <S> 源bean类型 * @param <T> 目标bean类型 * @return 目标bean对象list * @since 5.4.1 */ public static <S, T> List<T> copyList(Collection<S> source, Supplier<T> target, Converter converter) { return copyList(source, target, converter, null); } /** * 拷贝List Bean对象属性 * * @param source 源bean对象list * @param target 目标bean对象 * @param callback 回调对象 * @param <S> 源bean类型 * @param <T> 目标bean类型 * @return 目标bean对象list * @since 5.4.1 */ public static <S, T> List<T> copyList(Collection<S> source, Supplier<T> target, BiConsumer<S, T> callback) { return copyList(source, target, null, callback); } /** * 拷贝List Bean对象属性 * * @param source 源bean对象list * @param target 目标bean对象 * @param converter 转换器,无需可传{@code null} * @param callback 回调对象 * @param <S> 源bean类型 * @param <T> 目标bean类型 * @return 目标bean对象list */ public static <S, T> List<T> copyList(Collection<S> source, Supplier<T> target, Converter converter, BiConsumer<S, T> callback) { return source.stream().map(s -> { T t = target.get(); copy(s, t, converter); if (callback != null) { callback.accept(s, t); } return t; }).collect(Collectors.toList()); } /** * 将Bean转换为Map * * @param bean Bean对象 * @return {@link BeanMap} * @since 5.4.1 */ public static BeanMap toMap(Object bean) { return BeanMap.create(bean); } }
三、测试拷贝对象和集合
拷贝对象测试,再将拷贝的对象和源对象放入集合中对拷贝集合测试
public static void main(String[] args) { /** * 拷贝对象 */ //创建对象 TUser tUser = new TUser(); tUser.setName("李四"); //拷贝对象 TUser tUser2 = CglibUtil.copy(tUser,TUser.class); //打印结果 System.out.println(tUser2.getName()); /** * 拷贝集合 */ //创建集合 List<TUser> list1 = new ArrayList<>(); list1.add(tUser); list1.add(tUser2); //拷贝集合 List<TUser> list2 = CglibUtil.copyList(list1,TUser::new); //打印结果 System.out.println(JSONObject.toJSONString(list2)); }
结果打印
四、注意点
CglibUtil.copy拷贝对象的时候,目标对象被lombok注解@Accessors(chain = true)修饰报空指针
在拷贝对象上不可用注解 @Accessors ,反射获取不到对应的setter,因为这个链式生成的代码带了返回值,此注解会将set方法返回值改变
总结
以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。