日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > java >内容正文

java

Java对象复制

發布時間:2023/12/14 java 33 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Java对象复制 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

文章目錄

  • 前言
  • 何不可變類
  • 對象復制方式
    • 1.直接賦值
    • 2.淺拷貝
    • 3.深拷貝
  • 對象復制方案
    • 1.get/set
    • 2.Spring BeanUtils
    • 3.Apache BeanUtils
    • 4.BeanCopier
    • 5.Orika
    • 6.Dozer
    • 7.MapStruct
    • 8.Bean Mapping
    • 9.Bean Mapping ASM
    • 10.ModelMapper
    • 11.JMapper
    • 12.Json2Json
  • 復制方案選擇


前言

在我們實際項目開發過程中,我們經常需要將不同的兩個對象實例進行屬性復制,從而基于源對象的屬性信息進行后續操作,而不改變源對象的屬性信息。比如DTO數據傳輸對象和數據對象DO,我們需要將DO對象進行屬性復制到DTO,但是對象格式又不一樣,所以我們需要編寫映射代碼將對象中的屬性值從一種類型轉換成另一種類型。

這種轉換最原始的方式就是手動編寫大量的get/set代碼,屬性少的時候還好,屬性多的時候就非常繁瑣了,一個合格的程序員顯然不會僅僅局限于get/set。

針對這個問題,市場上誕生了很多方便的類庫,用于對象拷貝。常用的有apache BeanUtils、spring BeanUtils、Dozer、Orika等拷貝工具。

何不可變類

當類的實例一經創建,其內容便不可改變,即無法修改其成員變量。

Java中有一些特殊的類是不可變類,八個基本類型的包裝類和String類都屬于不可變類。

不可變類的特殊性:
有兩個不可變類對象,當兩個對象指向同一引用時,修改某一對象的值,不會對另一個對象造成影響。

下面舉例說明

  • 源碼:

    public static void main(String[] args) {Integer a = 1;String aa = "1";Integer b = a;String bb = aa;System.out.println("a修改前b:"+b);System.out.println("aa修改前bb:"+bb);a = 2;aa = "2";System.out.println("a修改后b:"+b);System.out.println("aa修改后bb:"+bb); }
  • debug:

  • 日志:

    a修改前b:1 aa修改前bb:1 a修改后b:1 aa修改后bb:1

由此可見,a和aa的修改不會影響b和bb的值。

方法參數的傳遞:

  • 基本類型傳遞的是值;
  • 引用類型傳遞的是對象的引用。
    • 不可變類型,在方法里修改了對象的值,也不會影響到原對象(不可變性);
    • 可變類型,在方法里修改了對象的值,原對象相應的值也會變動。

對象復制方式

對象復制有三種方式:直接賦值、淺拷貝、深拷貝。

1.直接賦值

  • 基本數據類型復制的是值;
  • 引用數據類型復制的是對象的引用,原始對象及目標對象引用的是同一個對象。

2.淺拷貝

創建一個新對象,然后將當前對象的非靜態字段復制到該新對象。

  • 基本數據類型復制的是值;
  • 引用數據類型復制的是對象的引用(不可變類型特殊)。

注意:String類型、Integer等基本數據類型的包裝類型,因為時不可變類型,所以即使進行的是淺拷貝,原始對象的改變并不會影響目標對象。

3.深拷貝

創建一個新對象,然后將當前對象的非靜態字段復制到該新對象。

  • 無論該字段是基本類型的還是引用類型,都復制獨立的一份。當你修改其中一個對象的任何內容時,都不會影響另一個對象的內容。

對象復制方案

一個好用的屬性復制方案,需要有哪些特性:

  • 支持基本的屬性復制;
  • 支持不同類型的屬性賦值,比如基本類型與其包裝類型等;
  • 支持不同字段名的屬性賦值,當然字段名應該盡量保持一致,但是實際業務中,確實會有字段名不一致的情況;
  • 淺拷貝/深拷貝,淺拷貝會引用同一對象,如果稍微不慎,同時改動對象,就會踩到意想不到的坑。
  • 市場上的對象轉換方案主要分類:

    • 直接編寫get、set代碼(硬編碼);
    • 通過反射實現;
    • 編譯期生成get、set代碼;
    • 基于AOP、ASM、CGlib等技術實現。

    12種對象轉換方案歸納:

    方案推薦指數性能指數原理點評
    get/set★★★☆☆★★★★★手寫get、set日常使用最多,性能好,只是較麻煩,需要手寫。
    Spring BeanUtils★★★☆☆★★★★☆基于反射日常使用較多,性能較好,推薦使用
    Apache BeanUtils☆☆☆☆☆★☆☆☆☆基于反射兼容性較差,性能差,不推薦使用
    BeanCopier★★★☆☆★★★★☆基于CGlib性能較好,使用也不復雜,可以使用
    Orika★★☆☆☆★★★☆☆基于Javasisst字節碼增強性能不太突出
    Dozer★☆☆☆☆★★☆☆☆基于反射的屬性映射(遞歸映射)性能較差,不太推薦使用
    MapStruct★★★★★★★★★★編譯期生成get、set性能好,結合到框架中使用方便,推薦使用
    Bean Mapping★★☆☆☆★★★☆☆基于反射性能一般,不太推薦使用
    Bean Mapping ASM★★★☆☆★★★★☆基于ASM字節碼增強性能較好,但暫時不夠靈活,可以使用
    ModelMapper★★★☆☆★★★☆☆基于反射性能一般,不太推薦使用
    JMapper★★★★☆★★★★★映射器方式實現性能較好,使用略微麻煩,可以使用
    Json2Json☆☆☆☆☆★☆☆☆☆基于JSON序列化和反序列化野路子,性能較差,不推薦使用

    分別測試這12種屬性轉換操作分別在一百次、一千次、一萬次、十萬次、一百萬次時候的性能時間對比。

    • BeanUtils.copyProperties是大家代碼里最常出現的工具類,但只要你不把它用錯成Apache包下的,而是使用Spring提供的,就基本還不會對性能造成多大影響。
    • 但如果說性能更好,可替代手動get、set的,還是MapStruct更好用,因為它本身就是在編譯期生成get、set代碼,和我們寫get、set一樣。
    • 其他一些組件包主要基于AOP、ASM、CGlib等技術手段實現的,所以也會有相應的性能損耗。

    1.get/set

    直接手寫get/set方法實現數據的復制。

    這種方式也是日常使用的最多的,性能較好,就是操作起來有點麻煩。尤其是當對象屬性較多的時候。

    減少手寫代碼的方式:

  • 通過一些快捷的操作方式,比如你可以通過 Shift+Alt 選中所有屬性,Shift+Tab 歸并到一列,接下來在使用 Alt 選中這一列,批量操作粘貼 userDTO.set 以及快捷鍵大寫屬性首字母,最后切換到結尾補充括號和分號,最終格式化一下就搞定了。
  • 通過IDEA的插件,如GenerateAllSetter插件。光標移至需生成get/set方法的對象名稱,alt+enter出現快捷選項,選擇需要生成的選項,自動生成相應的代碼。
  • 2.Spring BeanUtils

    同樣是基于反射的屬性拷貝(Introspector機制獲取到類的屬性來進行賦值操作)。Spring 提供的copyProperties要比Apache好用得多,這也是大家用得比較多的一種復制方式。

    Spring BeanUtils的實現方式非常簡單,就是對兩個對象中相同名字的屬性進行簡單的get/set,僅檢查屬性的可訪問性。成員變量賦值是基于目標對象的成員列表,并且會跳過ignoreProperties的以及在源對象中不存在,不會因為兩個對象之間的結構差異導致錯誤,但是必須保證同名的兩個成員變量類型相同。

    Introspector
    是一個專門處理bean的工具類,用來獲取Bean體系里的propertiesDescriptor、methodDescriptor利用反射獲取Method信息,是反射的上層。只進行一次反射解析,通過WeakReference靜態類級別緩存Method,在jvm不夠時會被回收。

    特點:

    • 字段名不一致,屬性無法復制;
    • 類型不一致,屬性無法復制。但是注意,如果類型為基本類型以及基本類型的包裝類,這種可以轉化;
    • 淺拷貝

    依賴:

    <dependency><groupId>org.springframework</groupId><artifactId>spring-beans</artifactId><version>5.2.8.RELEASE</version> </dependency>

    方法:

    /*** source:源對象* target:目標對象* editable:目標對象類的Class對象(需復制的屬性基于該Class,當該值為null時需復制的屬性基于目標對象的Class)* ignoreProperties:需忽略的屬性列表*/ BeanUtils.copyProperties(Object source, Object target)BeanUtils.copyProperties(Object source, Object target, Class<?> editable)BeanUtils.copyProperties(Object source, Object target, String... ignoreProperties)

    實現:

    public static void main(String[] args) {UserDTO userDTO = new UserDTO();userDTO.setId(1);userDTO.setUserName("哈哈");userDTO.setCreateTime(new Date());UserVO userVO = new UserVO();BeanUtils.copyProperties(userDTO, userVO);System.out.println(JSON.toJSONString(userVO)); }

    3.Apache BeanUtils

    推薦☆☆☆☆☆
    性能★☆☆☆☆
    手段:Introspector機制獲取到類的屬性來進行賦值操作
    點評:兼容性交差,效率較低,不建議使用

    Apache BeanUtils使用起來很方便,不過其底層源碼為了追求完美,加了過多的包裝,使用了很多反射,做了很多校驗,做了類型的轉換,甚至還會檢驗對象所屬的類的可訪問性,可謂相當復雜,過度的追求完美反而導致兼容性變差,也導致了性能較低,所以阿里巴巴開發手冊上強制避免使用Apache BeanUtils。

    特點:

    • 字段名不一致的屬性無法被復制;
    • 類型不一致的字段,將會進行默認類型轉化;
    • 淺拷貝

    依賴:

    <dependency><groupId>commons-beanutils</groupId><artifactId>commons-beanutils</artifactId><version>1.9.4</version> </dependency>

    方法:

    /*** dest:目標對象* orig:源對象*/ BeanUtils.copyProperties(Object dest, Object orig)

    實現:

    public static void main(String[] args) throws InvocationTargetException, IllegalAccessException {UserDTO userDTO = new UserDTO();userDTO.setId(1);userDTO.setUserName("哈哈");userDTO.setCreateTime(new Date());UserVO userVO = new UserVO();BeanUtils.copyProperties(userVO, userDTO);System.out.println(JSON.toJSONString(userVO)); }

    4.BeanCopier

    Cglib BeanCopier的原理與上面兩個Beanutils原理不太一樣,其主要使用CGlib字節碼技術動態生成一個代理類,代理類實現get和set方法。生成代理類過程存在一定開銷,但是一旦生成,我們可以緩存起來重復使用,所有Cglib性能相比以上兩種Beanutils性能比較好。

    特點:

    • 字段名不一致,屬性無法復制
    • 類型不一致,屬性無法復制。如果類型為基本類型/基本類型的包裝類型,這兩者也無法被拷貝。但可自定義轉換器實現不同類型的拷貝
    • 淺拷貝

    依賴:

    <dependency><groupId>cglib</groupId><artifactId>cglib</artifactId><version>3.3.0</version> </dependency>

    方法:

    /*** source 源Class* target 目Class* useConverter 是否使用轉換器* from 源對象* to 目標對象* converter 轉換器*/ BeanCopier beanCopier = BeanCopier.create(Class source, Class target, boolean useConverter); beanCopier.copy(Object from, Object to, Converter converter);

    實現:

    public static void main(String[] args) {UserDTO userDTO = new UserDTO();userDTO.setId(1);userDTO.setUserName("哈哈");userDTO.setCreateTime(new Date());UserVO userVO = new UserVO();BeanCopier beanCopier = BeanCopier.create(UserDTO.class, UserVO.class, false);beanCopier.copy(userDTO, userVO, null);System.out.println(JSON.toJSONString(userVO)); }

    5.Orika

    Orika也是一個跟Dozer類似的重量級屬性復制工具類,也提供諸如Dozer類似的功能。但是Orika無需使用繁瑣 XML配置,它自身提供一套非常簡潔的 API 用法,非常容易上手。

    Orika底層基于Javassist生成字段屬性的映射的字節碼,然后直接動態加載執行字節碼文件,相比于Dozer的這種使用反射原來的工具類,速度上會快很多。Orika的整個流程其實是需要使用到Java的反射的,只是在真正拷貝的屬性的時候沒有使用反射。

    Orika的執行流程:

  • 先通過內省(反射)把JavaBean的屬性(getset方法等)解析出來;
  • 進而匹配目標和源的屬性;
  • 接著根據這些屬性和目標/源的匹配情況基于Javasisst生成一個 GeneratedMapper的代理對象(真正的執行復制的對象)并放到緩存中;
  • 接著就基于這個對象的 mapAtoB和mapBtoA方法對屬性進行復制。
  • Orikade的使用需要創建兩個對象MapperFactory與MapperFacade,其中MapperFactory 可以用于字段映射,配置轉換器等,而MapperFacade 的作用就與Beanutils一樣,用于負責對象的之間的映射。

    特點:

    • 默認支持類型不一致(基本類型/包裝類型)轉換
    • 指定不同字段名映射關系,屬性可以被成功復制
    • 深拷貝

    依賴:

    <dependency><groupId>ma.glasnost.orika</groupId><artifactId>orika-core</artifactId><version>1.5.4</version> </dependency>

    方法:

    /*** sourceObject 源對象* destinationClass 目標Class* targetObject 目標對象*/ MapperFactory mapperFactory = new DefaultMapperFactory.Builder().build(); MapperFacade mapper = mapperFactory.getMapperFacade(); D targetObject = mapper.map(S sourceObject, Class<D> destinationClass);

    實現:

    public static void main(String[] args) {UserDTO userDTO = new UserDTO();userDTO.setId(1);userDTO.setUserName("哈哈");userDTO.setCreateTime(new Date());MapperFactory mapperFactory = new DefaultMapperFactory.Builder().build();MapperFacade mapper = mapperFactory.getMapperFacade();UserVO userVO = mapper.map(userDTO, UserVO.class);System.out.println(JSON.toJSONString(userVO)); }

    6.Dozer

    Dozer相對BeanUtils這類工具類來說,擁有許多高級功能,所以相對來說這是一個重量級工具類。其底層本質上還是使用了反射完成屬性的復制(屬性映射,遞歸的方式復制對象),所以執行速度并不是那么理想。

    Dozer需要我們新建一個DozerBeanMapper,這個類作用等同與BeanUtils,負責對象之間的映射,屬性復制。
    生成DozerBeanMapper實例需要加載配置文件,隨意生成代價比較高。因此在我們應用程序中,應該盡量使用單例模式,重復使用DozerBeanMapper。

    另外,強大的配置功能,我們可以通過XML、API或注解的方式配置源對象和目標對象屬性映射關系和類型轉換。

    特點:

    • 類型不一致的字段,屬性被復制
    • 通過配置字段名的映射關系,不一樣字段的屬性也被復制
    • 深拷貝

    依賴:

    <dependency><groupId>net.sf.dozer</groupId><artifactId>dozer</artifactId><version>5.4.0</version> </dependency>

    方法:

    /*** source 源對象* destinationClass 目標Class* target 目標對象*/ DozerBeanMapper mapper = new DozerBeanMapper(); T target = mapper.map(Object source, Class<T> destinationClass);

    實現:

    public static void main(String[] args) {UserDTO userDTO = new UserDTO();userDTO.setId(1);userDTO.setUserName("哈哈");userDTO.setCreateTime(new Date());DozerBeanMapper mapper = new DozerBeanMapper();UserVO userVO = mapper.map(userDTO, UserVO.class);System.out.println(JSON.toJSONString(userVO)); }

    7.MapStruct

    MapStruct運行速度與硬編碼差不多,這是因為他在編譯期間就生成了Java Bean屬性復制的代碼(屬性對應的get、set),運行期間就無需使用反射或者字節碼技術,所以確保了高性能。

    與硬編碼方式相比,不管使用反射,還是使用字節碼技術,這些都需要在代碼運行期間動態執行所以它們的執行速度都會比硬編碼慢很多。

    特點:

    • 名不一致,默認不支持復制
    • 類型不一致,默認不支持復制(但支持基本類型與包裝類型、基本類型的包裝類型與String的自動轉換)
    • 可通注解配置實現名稱不一致、類型不一致的復制
    • 深拷貝

    依賴:

    <dependency><groupId>org.mapstruct</groupId><artifactId>mapstruct</artifactId><version>1.3.1.Final</version> </dependency>

    插件:
    由于MapStruct需要在編譯器期間生成代碼,所以我們需要maven-compiler-plugin插件中配置。

    <plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-compiler-plugin</artifactId><version>3.8.1</version><configuration><source>1.8</source> <!-- depending on your project --><target>1.8</target> <!-- depending on your project --><annotationProcessorPaths><path><groupId>org.mapstruct</groupId><artifactId>mapstruct-processor</artifactId><version>1.3.1.Final</version></path><path><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>1.18.12</version></path><!-- other annotation processors --></annotationProcessorPaths></configuration> </plugin>

    方法:

    @Mapper public interface UserMapper {UserMapper INSTANCE = Mappers.getMapper(UserMapper.class);@Mappings({@Mapping(source = "id", target = "id"),@Mapping(source = "createTime", target = "createTime")})UserVO dtoToVo(UserDTO userDTO); }

    編譯:
    MapStruct沒有想象中的神奇,其實就是在編譯期生成了接口的實現類,里面的轉換方法實現了轉換功能。相當于幫我們手寫get/set設值,所以它的性能會很好。

    public class UserMapperImpl implements UserMapper {public UserMapperImpl() {}public UserVO dtoToVo(UserDTO userDTO) {if (userDTO == null) {return null;} else {UserVO userVO = new UserVO();userVO.setIdd(userDTO.getId());userVO.setCreateTime(userDTO.getCreateTime());userVO.setUserName(userDTO.getUserName());return userVO;}} }

    實現:

    public static void main(String[] args) {UserDTO userDTO = new UserDTO();userDTO.setId(1);userDTO.setUserName("哈哈");userDTO.setCreateTime(new Date());UserVO userVO = UserMapper.INSTANCE.dtoToVo(userDTO);System.out.println(JSON.toJSONString(userVO)); }

    可能出現的問題:

    • 如果我們對象使用 Lombok 的話,使用 @Mapping指定不同字段名,編譯期間可能會拋出如下的錯誤

      原因主要是因為Lombok也需要編譯期間自動生成代碼,這就可能導致兩者沖突,當MapStruct生成代碼時,還不存在Lombok生成的代碼。解決辦法可以在 maven-compiler-plugin插件配置中加入Lombok。

    8.Bean Mapping

    基于反射的屬性拷貝。0.0.2版本引入了@BeanMapping,通過@BeanMapping注解可實現靈活的復制方式。

    注解定義在 bean-mapping-api 模塊中,bean-mapping-core 會默認引入此模塊。

    特點:

    • 名不一致,不支持復制
    • 類型不一致,不支持復制(但支持基本類型轉為包裝類型,反過來不支持)
    • 通過@BeanMapping注解來靈活控制復制,支持名稱不一致的復制、類型不一致的復制和控制是否復制。
    • 淺拷貝

    依賴:

    <dependency><groupId>com.github.houbb</groupId><artifactId>bean-mapping-core</artifactId><version>0.2.5</version> </dependency>

    注解:

    @Inherited @Documented @Target(ElementType.FIELD) @Retention(RetentionPolicy.RUNTIME) public @interface BeanMapping {/*** 字段別名* 如果不填,則默認使用字段的名稱* 會將source的屬性值賦值給target和當前name屬性一致的屬性* @return 字段別名*/String name() default "";/*** 生效條件(默認為生效)* 1.當放在source字段上時,表示是否將值賦給target字段* 2.當放在target字段上時,表示是否接受賦值。* 3.source+target只有同時生效時,才會發生賦值。* @return 具體的生效實現*/Class<? extends ICondition> condition() default ICondition.class;/*** 類型轉換(默認不進行轉換)* 當source的值轉換后可以設置給target,才會將source轉換后的值賦值給target對應屬性,其他情況不會對值產生影響。* @return 具體的轉換實現*/Class<? extends IConvert> convert() default IConvert.class;}

    方法:

    /*** source 源對象* target 目標對象*/ BeanUtil.copyProperties(Object source, Object target)

    實現:

    public static void main(String[] args) {UserDTO userDTO = new UserDTO();userDTO.setId(1);userDTO.setUserName("哈哈");userDTO.setCreateTime(new Date());UserVO userVO = new UserVO();BeanUtil.copyProperties(userDTO, userVO);System.out.println(JSON.toJSONString(userVO)); }

    9.Bean Mapping ASM

    推薦★★★☆☆
    性能★★★★☆
    手段:基于ASM字節碼框架實現
    點評:與普通的Bean Mapping 相比,性能有所提升,可以使用。

    Bean Mapping基于ASM的字節碼增強技術的復制方式要比Bean Mapping普通的方式新能要提升不少,但有個缺點就是暫不支持@BeanMapping注解等更加豐富的功能。

    特點:

    • 名不一致,不支持復制
    • 類型不一致,不支持復制(但支持基本類型轉為包裝類型,反過來不支持)
    • 效率比傳統的Bean Mapping要好些,但暫不支持@BeanMapping注解的靈活復制
    • 淺拷貝

    依賴:

    <dependency><groupId>com.github.houbb</groupId><artifactId>bean-mapping-asm</artifactId><version>0.2.5</version> </dependency>

    方法:

    /*** source 源對象* target 目標對象*/ AsmBeanUtil.copyProperties(Object source, Object target)

    實現:

    public static void main(String[] args) {UserDTO userDTO = new UserDTO();userDTO.setId(1);userDTO.setUserName("哈哈");userDTO.setCreateTime(new Date());UserVO userVO = new UserVO();AsmBeanUtil.copyProperties(userDTO, userVO);System.out.println(JSON.toJSONString(userVO)); }

    10.ModelMapper

    ModelMapper是利用反射的原理實現的。轉換對象數量較少時性能不錯,如果同時大批量轉換對象,性能有所下降。

    依賴:

    <dependency><groupId>org.modelmapper</groupId><artifactId>modelmapper</artifactId><version>2.3.0</version> </dependency>

    實現:
    簡單使用

    public static void main(String[] args) {UserDTO userDTO = new UserDTO();userDTO.setId(1);userDTO.setUserName("哈哈");userDTO.setCreateTime(new Date());UserVO userVO = new UserVO();ModelMapper modelMapper = new ModelMapper();modelMapper.map(userDTO, userVO);System.out.println(JSON.toJSONString(userVO)); }

    ModelMapper的具體使用可參考文章:實體映射類庫(modelmapper和MapStruct)

    11.JMapper

    JMapper通過映射器方式實現。

    依賴:

    <dependency><groupId>com.googlecode.jmapper-framework</groupId><artifactId>jmapper-core</artifactId><version>1.6.0</version> </dependency>

    實現:

    public static void main(String[] args) {UserDTO userDTO = new UserDTO();userDTO.setId(1);userDTO.setUserName("哈哈");userDTO.setCreateTime(new Date());JMapper<UserVO, UserDTO> jMapper = new JMapper<>(UserVO.class, UserDTO.class, new JMapperAPI().add(JMapperAPI.mappedClass(UserVO.class).add(JMapperAPI.attribute("id").value("id")).add(JMapperAPI.attribute("userName").value("userName")).add(JMapperAPI.attribute("createTime").value("createTime"))));UserVO userVO = jMapper.getDestination(userDTO);System.out.println(JSON.toJSONString(userVO)); }

    12.Json2Json

    這種通過JSON序列化和反序列化的方式,把源對象轉為JSON串,再把JSON串轉為目標對象,雖然也能達到復制的目的,但不推薦使用。

    實現:

    public static void main(String[] args) {UserDTO userDTO = new UserDTO();userDTO.setId(1);userDTO.setUserName("哈哈");userDTO.setCreateTime(new Date());UserVO userVO = JSON.parseObject(JSON.toJSONString(userDTO), UserVO.class);System.out.println(JSON.toJSONString(userVO)); }

    復制方案選擇

  • 手寫get/set肯定是效率最高的;
  • 不要使用Apache Beanutils,因為效率低,阿里巴巴規范都直接禁止使用;
  • 一般情況使用Spring Beanutils就可以了,效率OK,且本來就是Spring中的東西,不用依賴其它包。

  • 參考文章:對比 12 種 Bean 自動映射工具

    總結

    以上是生活随笔為你收集整理的Java对象复制的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。