java如何拷貝復制對象和集合問題
在Java中常見的對象拷貝方式是使用cglib,Cglib的性能是目前公認最好的,用于解決Bean拷貝的性能問題
下面是以cglib封裝的工具類實現(xiàn)對象和集合的拷貝
一、引入依賴
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>3.3.0</version>
<scope>compile</scope>
</dependency>二、創(chuàng)建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>
* 此方法通過指定目標類型自動創(chuàng)建之,然后拷貝屬性
*
* @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>
* 此方法通過指定目標類型自動創(chuàng)建之,然后拷貝屬性
*
* @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) {
/**
* 拷貝對象
*/
//創(chuàng)建對象
TUser tUser = new TUser();
tUser.setName("李四");
//拷貝對象
TUser tUser2 = CglibUtil.copy(tUser,TUser.class);
//打印結果
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);
//打印結果
System.out.println(JSONObject.toJSONString(list2));
}結果打印

四、注意點
CglibUtil.copy拷貝對象的時候,目標對象被lombok注解@Accessors(chain = true)修飾報空指針
在拷貝對象上不可用注解 @Accessors ,反射獲取不到對應的setter,因為這個鏈式生成的代碼帶了返回值,此注解會將set方法返回值改變
總結
以上為個人經驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關文章
使用Spring Boot搭建Java web項目及開發(fā)過程圖文詳解
這篇文章主要介紹了使用Spring Boot搭建Java web項目及開發(fā)過程,本文通過圖文并茂的形式給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下2020-06-06
Java concurrency之AtomicLongFieldUpdater原子類_動力節(jié)點Java學院整理
AtomicLongFieldUpdater可以對指定"類的 'volatile long'類型的成員"進行原子更新。它是基于反射原理實現(xiàn)的。下面通過本文給大家分享Java concurrency之AtomicLongFieldUpdater原子類的相關知識,感興趣的朋友一起看看吧2017-06-06
Java?8中讀取文件內容?Files.lines()方法使用示例
這篇文章主要介紹了Java?8中讀取文件內容Files.lines()方法如何使用示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2023-07-07
mybatis參數(shù)類型不匹配錯誤argument type mismatch的處理方案
這篇文章主要介紹了mybatis參數(shù)類型不匹配錯誤argument type mismatch的處理方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-01-01
springcloud?feign?接口指定接口服務ip方式
這篇文章主要介紹了springcloud?feign?接口指定接口服務ip方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-03-03

