Skip to content
Advertisement

Apache Commons lang: What’s difference between SerializationUtils.clone() and BeanUtils.cloneBean(), when to use which

While writing tests I came across a requirement to clone an object. found 2 Utill classes by apache-commons then I tried to find which one should I use, I’ve tried to find the diff by reading out both API doc but didn’t find which should I use when

BeanUtils cloneBean() API doc

As per doc: Clone a bean based on the available property getters and setters, even if the bean class itself does not implement Cloneable.

Doubt: should i use this on DTO cloning ?

SerializationUtils clone() API doc

As per doc:

Deep clone an Object using serialization.

This is many times slower than writing clone methods by hand on all objects in your object graph. However, for complex object graphs, or for those that don’t support deep cloning this can be a simple alternative implementation. Of course, all the objects must be Serializable.

Doubt: should I use it for both DTO and Entity Object ? or only for Entity

Advertisement

Answer

The SerializationUtils will always produce a deep-copy. It will create a string of each field (it is called serialization) and parses the string back into a new object (deserialization).

This is quite slow, but you have the guarantee, that your copy is a deep copy.
A deep-copy means: All fields are new objects (and not a reference to a old object).

BeanUtils.cloneBean() on the other hand, will create a shallow copy of your object. Here is some code to explain what is the difference:

@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']"

    
}

So to your questions: A deep-copy is “safer”, you can’t modify fields of the original object. This side-effect on shallow copies is often unwanted. Almost always, you need a deep copy.
Serialization is quite slow, so the best way is a copy-method or a copy-constructor.

User contributions licensed under: CC BY-SA
2 People found this is helpful
Advertisement