基于面向对象和各种设计要求,一个分层的Java系统中存在各种 VO、DTO、BO、PO 之类的对象,同一个实体的不同对象需要大量的属性复制,为了避免手动操作,需要一种便捷对象浅复制工具类,下面是各个常见工具对比。

列举

//cglib
net.sf.cglib.beans.BeanCopier.create
net.sf.cglib.beans.BeanCopier.copy
//spring-beans
org.springframework.beans.BeanUtils.copyProperties
//commons-beanutils
org.apache.commons.beanutils.BeanUtils.copyProperties
org.apache.commons.beanutils.PropertyUtils.copyProperties

原理

以上4种方式都是通过自动调用原对象的getter方法,再用目标对象的setter方法设置进去,区别在于BeanCopier先通过create创建了一个以BeanCopier派生的动态代理类,其创建的copy方法实现包含以上所有getter和setter的调用过程,调用copy可以达到原生代码方式的性能;而其他所有方式如spring-beans和commons-beanutils的实现都是通过反射逐个调用getter和setter,性能相比前者较差。

细节

细节 Apache-PropertyUtils Apache-BeanUtils Spring-BeanUtils Cglib-BeanCopier
相同属性名,不同类型转换Converter扩展 NO Yes Yes Yes,较难用,需要对每一种属性类型都做转换
相同属性名,Integer和int的处理 OK OK OK 不拷贝,忽略该属性
相同属性名,Long和Integer的处理 异常报错 OK,自动互转 不拷贝,忽略该属性 不拷贝,忽略该属性
对基本类型null值处理(Integer,Long等) OK 特殊,会将null转为0,用Converter后解决 OK OK
对source特殊属性的限制:(Date,BigDecimal等) OK NO,异常出错,必须用Converter才行 OK OK
Get和set方法不匹配的处理 OK,忽略该属性 OK,忽略该属性 OK,忽略该属性 创建异常(仅限source有get方法在target中找不到对应set方法)
调用异常处理 需处理异常 需处理异常 RuntimeException RuntimeException

需要兼容性的场景,优先spring-beans提供的BeanUtils,功能强大,兼容性最好。需要性能的场景,优先选择cglib提供的BeanCopier,性能最好(注意需要缓存create结果)。

还有一项需要注意的是所有拷贝都是浅拷贝,注意属性引用不变,避免新老对象同时读写引起问题,这需要通过场景约束。

结论

事实上,由于不同工具类实现不同,细节差异非常多,一个团队最好通过规范统一使用某一个,并对其熟悉和理解,不必追求万能的工具类。我在新项目中选择了BeanCopier,并通过场景和限制约定避免踩坑。

  • 场景约束:主要用于同模型的DO、DTO和VO等之间转换。
  • 限制约定:要求两者同名属性具有严格相同类型,且其getter和setter一一对应,不能包含特殊逻辑。

Java对象拷贝备忘的更多相关文章

  1. 0. Java虚拟机系列备忘预览图

    打算把Java虚拟机这块单独弄一个主题出来,做做备忘,结构如图所示: 后面还有一部分待更新...

  2. JAVA 对象拷贝

    1.java里的clone分为:  A:浅复制(浅克隆): 浅复制仅仅复制所考虑的对象,而不复制它所引用的对象.  b:深复制(深克隆):深复制把要复制的对象所引用的对象都复制了一遍.  Java中对 ...

  3. java基础知识备忘

    1.java内存分配 a.寄存器cup -- 暂不涉及 b.本地方法栈  -- 虚拟机调用windows功能用的,比如创建文件夹 c.方法区  -- 存放 .class文件,负责存放方法 d.栈 -- ...

  4. java对象拷贝和复制

    参考文章:http://blog.csdn.net/XIAXIA__/article/details/41652057 解决问题:深拷贝.浅拷贝 和普通的对象赋值有什么区别? 对象复制 例如:Pers ...

  5. Java输入输出流备忘

    重要博客: http://blog.csdn.net/hguisu/article/details/7418161 File dir = new File("\\root");   ...

  6. Java Socket基础[备忘]

    1.服务端----Server.java import javax.swing.*; import java.io.*; import java.net.*; import java.awt.*; i ...

  7. ruby正则表带式对象使用备忘

    ruby对于正则表达式的使用是非常灵活的,提供了专门的正则表达式对象Regexp.其包括match实例方法,字符串也含有该方法.so可以这么做: /a/ =~ "a" " ...

  8. java集合框架备忘

    List,Set,Map三者的区别? List(对付顺序的好帮手): List接口存储一组不唯一(可以有多个元素引用相同的对象),有序的对象 Set(注重独一无二的性质): 不允许重复的集合.不会有多 ...

  9. Java 对象拷贝方式

    (1)BeanUtils.cloneBean()使用: http://www.cnblogs.com/fervour/archive/2009/12/18/1627868.html package c ...

随机推荐

  1. CDH 离线安装 CM

    CDH支持Yum包,Tar包,RPM包,Cloudera Manager(CM)四种安装方式 Cloudera Manager(CM) 用于CDH集群管理,可进行节点安装,配置,服务管理等,提供Web ...

  2. 【WPF学习】第二十九章 元素绑定——将元素绑定到一起

    数据banding的最简单情形是,源对象时WPF元素而且源属性是依赖性属性.前面章节解释过,依赖项属性具有内置的更改通知支持.因此,当在源对象中改变依赖项属性的值时,会立即更新目标对象中的绑定属性.这 ...

  3. mybatis入门案例自定义实现

    mybatis入门案例自定义实现 一.需要实现的类和接口 public static void main(String[] args) throws Exception{ //1.读取配置文件 Inp ...

  4. Leetcode 题目整理-4 Longest Common Prefix & Remove Nth Node From End of List

    14. Longest Common Prefix Write a function to find the longest common prefix string amongst an array ...

  5. C语言创建文件夹

    问题需求:在程序中需要使用文件夹时,一般可以先在程序目录或某一路径下创建一个文件夹,然后使用该文件夹. 这种方法比较麻烦,需提前创建文件夹. 使用C语言创建文件夹的代码可以如下: #include & ...

  6. Java基础知识之设计模式--单例模式

    Java设计模式--单例模式 声明:本文根据慕课网汤小洋老师的精品课程整理来的:慕课网 什么是设计模式(Design Pattern)? 设计模式是一套被反复使用,多数人知晓的,经过分类编目的,代码设 ...

  7. hashmap 的边遍历边存储

    PS: Hashmap 的一边遍历边存储,可解决例如两数之和. 无重复最长子串问题等,代码为cpp格式. 以无重复最长子串为例. class Solution { public: int length ...

  8. python学习Day02

    [主要内容] 1. 循环. while循环 while 条件: 代码块(循环体) 执行流程: 1. 判断条件是否为真. 如果真. 执行代码块 2. 再次判断条件是否为真...... 3. 当条件为假. ...

  9. sougn开源,自己写的一个项目

    源代码:http://yun.baidu.com/share/link?shareid=1504480803&uk=2739888323 联系方式:1034465036@qq.com

  10. java.lang.NullPointerException at org.apache.jsp.**_jsp.jspInit(**_jsp.java)tomcat启动异常解决方法

    今天遇到的其他一个问题就是,启动tomcat时,报:java.lang.NullPointerException at org.apache.jsp.**_jsp.jspInit(index_jsp. ...