Apache Commons Lang:SerializationUtils.clone() 和 BeanUtils.cloneBean() 有什么区别?何时使用哪个?

3
在编写测试时,我遇到了克隆对象的要求。我找到了两个Apache-commons的Utill类,然后尝试找出应该使用哪一个,我试图通过阅读两个API文档来找到区别,但是没有找到应该在什么情况下使用哪个。 BeanUtils cloneBean() API doc 根据文档:
基于可用的属性getter和setter克隆bean,即使bean类本身没有实现Cloneable。
疑问:我应该在DTO克隆中使用它吗? SerializationUtils clone() API doc 根据文档:
使用序列化深度克隆对象。
这种方法比手动编写对象图中所有对象的克隆方法慢得多。但是,对于复杂的对象图或不支持深层克隆的对象,这可以作为简单的替代实现。当然,所有对象都必须是可序列化的。 疑问:我应该同时在DTO和实体对象中使用它吗?还是只用于实体对象?
1个回答

7
SerializationUtils 总是会产生一个深拷贝。它会创建每个字段的字符串(称为序列化),然后将该字符串解析回一个新对象(反序列化)。
这相当慢,但您可以保证您的副本是深拷贝。 深拷贝意味着:所有字段都是新对象(而不是指向旧对象的引用)。
另一方面,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']"

    
}

回答你的问题:深复制更加“安全”,您无法修改原始对象的字段。浅复制的这种副作用通常是不想要的。几乎总是需要深复制。
序列化速度较慢,因此最好的方法是使用复制方法或复制构造函数


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接