java如何拷貝復(fù)制對象和集合問題
在Java中常見的對象拷貝方式是使用cglib,Cglib的性能是目前公認(rèn)最好的,用于解決Bean拷貝的性能問題
下面是以cglib封裝的工具類實(shí)現(xiàn)對象和集合的拷貝
一、引入依賴
<dependency> <groupId>cglib</groupId> <artifactId>cglib</artifactId> <version>3.3.0</version> <scope>compile</scope> </dependency>
二、創(chuàng)建CglibUtil工具類
其中包含對象和集合的拷貝,還封裝了Bean轉(zhuǎn)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對象屬性到目標(biāo)類型<br> * 此方法通過指定目標(biāo)類型自動創(chuàng)建之,然后拷貝屬性 * * @param <T> 目標(biāo)對象類型 * @param source 源bean對象 * @param targetClass 目標(biāo)bean類,自動實(shí)例化此對象 * @return 目標(biāo)對象 */ public static <T> T copy(Object source, Class<T> targetClass) { return copy(source, targetClass, null); } /** * 拷貝Bean對象屬性<br> * 此方法通過指定目標(biāo)類型自動創(chuàng)建之,然后拷貝屬性 * * @param <T> 目標(biāo)對象類型 * @param source 源bean對象 * @param targetClass 目標(biāo)bean類,自動實(shí)例化此對象 * @param converter 轉(zhuǎn)換器,無需可傳{@code null} * @return 目標(biāo)對象 */ 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 目標(biāo)bean對象 */ public static void copy(Object source, Object target) { copy(source, target, null); } /** * 拷貝Bean對象屬性 * * @param source 源bean對象 * @param target 目標(biāo)beBeanCopierCachean對象 * @param converter 轉(zhuǎn)換器,無需可傳{@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> 目標(biāo)bean類型 * @param source 源bean對象list * @param target 目標(biāo)bean對象 * @return 目標(biāo)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 目標(biāo)bean對象 * @param converter 轉(zhuǎn)換器,無需可傳{@code null} * @param <S> 源bean類型 * @param <T> 目標(biāo)bean類型 * @return 目標(biāo)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 目標(biāo)bean對象 * @param callback 回調(diào)對象 * @param <S> 源bean類型 * @param <T> 目標(biāo)bean類型 * @return 目標(biāo)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 目標(biāo)bean對象 * @param converter 轉(zhuǎn)換器,無需可傳{@code null} * @param callback 回調(diào)對象 * @param <S> 源bean類型 * @param <T> 目標(biāo)bean類型 * @return 目標(biāo)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轉(zhuǎn)換為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) { /** * 拷貝對象 */ //創(chuàng)建對象 TUser tUser = new TUser(); tUser.setName("李四"); //拷貝對象 TUser tUser2 = CglibUtil.copy(tUser,TUser.class); //打印結(jié)果 System.out.println(tUser2.getName()); /** * 拷貝集合 */ //創(chuàng)建集合 List<TUser> list1 = new ArrayList<>(); list1.add(tUser); list1.add(tUser2); //拷貝集合 List<TUser> list2 = CglibUtil.copyList(list1,TUser::new); //打印結(jié)果 System.out.println(JSONObject.toJSONString(list2)); }
結(jié)果打印
四、注意點(diǎn)
CglibUtil.copy拷貝對象的時候,目標(biāo)對象被lombok注解@Accessors(chain = true)修飾報空指針
在拷貝對象上不可用注解 @Accessors ,反射獲取不到對應(yīng)的setter,因?yàn)檫@個鏈?zhǔn)缴傻拇a帶了返回值,此注解會將set方法返回值改變
總結(jié)
以上為個人經(jīng)驗(yàn),希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
使用Spring Boot搭建Java web項(xiàng)目及開發(fā)過程圖文詳解
這篇文章主要介紹了使用Spring Boot搭建Java web項(xiàng)目及開發(fā)過程,本文通過圖文并茂的形式給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2020-06-06Java concurrency之AtomicLongFieldUpdater原子類_動力節(jié)點(diǎn)Java學(xué)院整理
AtomicLongFieldUpdater可以對指定"類的 'volatile long'類型的成員"進(jìn)行原子更新。它是基于反射原理實(shí)現(xiàn)的。下面通過本文給大家分享Java concurrency之AtomicLongFieldUpdater原子類的相關(guān)知識,感興趣的朋友一起看看吧2017-06-06Java?8中讀取文件內(nèi)容?Files.lines()方法使用示例
這篇文章主要介紹了Java?8中讀取文件內(nèi)容Files.lines()方法如何使用示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-07-07mybatis參數(shù)類型不匹配錯誤argument type mismatch的處理方案
這篇文章主要介紹了mybatis參數(shù)類型不匹配錯誤argument type mismatch的處理方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-01-01Spring使用注解實(shí)現(xiàn)Bean的自動裝配
大家好,本篇文章主要講的是Spring使用注解實(shí)現(xiàn)Bean的自動裝配,感興趣的同學(xué)趕快來看一看吧,對你有幫助的話記得收藏一下2022-02-02springcloud?feign?接口指定接口服務(wù)ip方式
這篇文章主要介紹了springcloud?feign?接口指定接口服務(wù)ip方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-03-03