Apache Commons lang:SerializationUtils.clone() 和 BeanUtils.cloneBean() 有啥区别,啥时候使用哪个

Posted

技术标签:

【中文标题】Apache Commons lang:SerializationUtils.clone() 和 BeanUtils.cloneBean() 有啥区别,啥时候使用哪个【英文标题】:Apache Commons lang: What's difference between SerializationUtils.clone() and BeanUtils.cloneBean(), when to use whichApache Commons lang:SerializationUtils.clone() 和 BeanUtils.cloneBean() 有什么区别,什么时候使用哪个 【发布时间】:2021-11-17 11:22:57 【问题描述】:

在编写测试时,我遇到了克隆对象的要求。通过 apache-commons 找到了 2 个 Utill 类,然后我试图找到我应该使用哪一个, 我试图通过阅读两个 API 文档来找到差异,但没有找到我应该在什么时候使用哪个

BeanUtils cloneBean() API doc

根据文档: 根据可用的属性 getter 和 setter 克隆 bean,即使 bean 类本身没有实现 Cloneable。

疑问:我应该在 DTO 克隆上使用它吗?

SerializationUtils clone() API doc

根据文档:

使用序列化深度克隆对象。

这比在对象图中的所有对象上手动编写克隆方法要慢很多倍。但是,对于复杂的对象图,或者不支持深度克隆的对象图,这可能是一个简单的替代实现。当然,所有的对象都必须是可序列化的。

疑问:我应该将它用于 DTO 和实体对象吗?或仅适用于实体

【问题讨论】:

【参考方案1】:

SerializationUtils 将始终生成 deep-copy。它将为每个字段创建一个字符串(称为序列化)并将字符串解析回一个新对象(反序列化)。

这很慢,但您可以保证,您的副本是深层副本。 深拷贝意味着:所有字段都是新对象(而不是对旧对象的引用)。

另一方面,BeanUtils.cloneBean() 将创建对象的浅表副本。下面是一些代码来解释有什么区别:

@Data // lombok annotation, will create getters, setters, equals and hashcode
public class ObjectA implements Serializeable 
    private List<String> values = new ArrayList<>();



public static main() 

    ObjectA objectA = new ObjectA();
    objectA().getValues().add("A");

    ObjectA beanClone = (ObjectA) BeanUtils.cloneBean(objectA);
    ObjectA serialClone = SerializationUtils.clone(objectA);

    log.info("Reference-Check: Bean is same: ", objectA == beanClone); // <- false
    log.info("Reference-Check: Bean-Value is same: ", objectA.getValues() == beanClone.getValues()); // <- true

    log.info("Reference-Check: Serial is same: ", objectA == serialClone); // <- false
    log.info("Reference-Check: Serial-Value is same: ", objectA.getValues() == serialClone.getValues()); // <- false

     
    serialClone.getValues().add("B");
    printValues(serialClone.getValues()); // <- prints "['A', 'B']"
    printValues(objectA.getValues()); // <- prints "['A']";

    beanClone.getValues().add("B");
    printValues(beanClone.getValues()); // <- prints "['A', 'B']"
    printValues(objectA.getValues()); // <- prints "['A', 'B']"

    


所以对于您的问题:深拷贝“更安全”,您不能修改原始对象的字段。这种对浅拷贝的副作用通常是不需要的。 几乎总是需要深拷贝。 序列化很慢,所以最好的方法是复制方法或copy-constructor。

【讨论】:

以上是关于Apache Commons lang:SerializationUtils.clone() 和 BeanUtils.cloneBean() 有啥区别,啥时候使用哪个的主要内容,如果未能解决你的问题,请参考以下文章

找不org.apache.commons.lang3.builder.EqualsBuilder和commons-lang下载链接

java.lang.ClassNotFoundException: org.apache.commons.lang.exception.NestableRuntimeException

有com.springsource.org.apache.commons.lang-2.4.0.jar还需要commons-lang-2.3.jar冲突吗

StringUtils在commons-lang3和commons-lang中的区别

解决import org.apache.commons.lang.StringUtils问题

UCanAccess 升级 Apache Commons Lang 版本