Attention can view more fans exclusive blog~

Shallow copy

  1. A member variable of the base data type that is passed in value (a copy of the property value to the new object).
  2. A member variable that refers to a data type, such as an array or an object of a class, is passed by reference (the reference value (memory address) of the member variable is copied to the new object).

Deep copy

  1. A member variable of the base data type that is passed in value (a copy of the property value to the new object).
  2. A member variable that refers to a data type, such as an array, an object of a class, etc., reallocates memory and assigns a copy of the member variable to the new object (the contents of the member variable are copied to the new memory, and the new object points to the new memory address).

In the development process, if the same List is used in multiple places and the contents of the List elements are modified, deep copy is required to avoid interference with each other.

Confusion points (shallow copies that look like deep copies)

/ / shallow copy
List<Msg> source = new ArrayList<>();
List<Msg> target= new ArrayList<>(source);

/ / shallow copy
List<Msg> target= new ArrayList<>();
target.addAll(source);
Copy the code

Examples of confusion points

@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class Msg implements Serializable {

    private static final long serialVersionUID = -3893311742256460336L;
    private String detail;

    private String body;
}

public static void main( String[] args ) {
    List<Msg> msgs = new ArrayList<>();
    Msg msg1 = new Msg("davids"."body");
    msgs.add(msg1);
    for (Msg msg : msgs) {
        msg.setBody("one" + msg.getBody());
        System.out.println(msg);
    }

    for (Msg msg : msgs) {
        msg.setBody("two"+ msg.getBody()); System.out.println(msg); }}// output
Msg(detail=davids, body=onebody)
Msg(detail=davids, body=twoonebody)

// Try new ArrayList<>(source);
public static void main( String[] args ) {
    List<Msg> msgs = new ArrayList<>();
    Msg msg1 = new Msg("davids"."body");
    msgs.add(msg1);
    List<Msg> one = new ArrayList<>(msgs);
    for (Msg msg : one) {
        msg.setBody("one" + msg.getBody());
        System.out.println(msg);
    }

    List<Msg> two = new ArrayList<>(msgs);
    for (Msg msg : two) {
        msg.setBody("two"+ msg.getBody()); System.out.println(msg); }}// output as before new
Msg(detail=davids, body=onebody)
Msg(detail=davids, body=twoonebody)
// Look at the source code
public ArrayList(Collection<? extends E> c) {
   elementData = c.toArray();
    if((size = elementData.length) ! =0) {
        if(elementData.getClass() ! = Object[].class)// Arrays. CopyOf
            elementData = Arrays.copyOf(elementData, size, Object[].class);
    } else {
        this.elementData = EMPTY_ELEMENTDATA; }}// Arrays.copyOf
public static <T,U> T[] copyOf(U[] original, int newLength, Class<? extends T[]> newType) {
    @SuppressWarnings("unchecked")
    T[] copy = ((Object)newType == (Object)Object[].class)
        ? (T[]) new Object[newLength]
        : (T[]) Array.newInstance(newType.getComponentType(), newLength);
    // An internal call to system. arrayCopy ostensibly generates a new array, but actually the pointer points to the same block of memory
    System.arraycopy(original, 0, copy, 0,
                     Math.min(original.length, newLength));
    return copy;
}

// Try target.addall (source);
public static void main( String[] args ) {
    List<Msg> msgs = new ArrayList<>();
    Msg msg1 = new Msg("davids"."body");
    msgs.add(msg1);
    List<Msg> one = new ArrayList<>();
    one.addAll(msgs);
    for (Msg msg : one) {
        msg.setBody("one" + msg.getBody());
        System.out.println(msg);
    }

    List<Msg> two = new ArrayList<>();
    two.addAll(msgs);
    for (Msg msg : two) {
        msg.setBody("two"+ msg.getBody()); System.out.println(msg); }}// Output is the same as before
Msg(detail=davids, body=onebody)
Msg(detail=davids, body=twoonebody)
// Look at the source code
public boolean addAll(Collection<? extends E> c) {
    Object[] a = c.toArray();
    int numNew = a.length;
    ensureCapacityInternal(size + numNew);
    Arraycopy creates a new array, but the pointer points to the same block of memory
    System.arraycopy(a, 0, elementData, size, numNew);
    size += numNew;
    returnnumNew ! =0;
}
Copy the code

How to deep copy

  1. Use reflection to obtain a member of the source object variable to be set (such as: common BeanUtils, org.apache.com mons. BeanUtils/org springframework. Beans. BeanUtils, etc.)
    1. BeanUtils.cloneBean()
    2. BeanUtils.copyProperties()
  2. Using IO serialization (HuTool)
    1. cn.hutool.core.util.ObjectUtil.cloneByStream

Deep-copy example

// BeanUtils.cloneBean
@SneakyThrows
public static void main( String[] args ) {
    List<Msg> msgs = new ArrayList<>();
    Msg msg1 = new Msg("davids"."body");
    msgs.add(msg1);
    for (Msg msg : msgs) {
        Msg msg2 = (Msg) BeanUtils.cloneBean(msg);
        msg2.setBody("one" + msg2.getBody());
        System.out.println(msg2);
    }

    for (Msg msg : msgs) {
        Msg msg2 = (Msg) BeanUtils.cloneBean(msg);
        msg2.setBody("two"+ msg2.getBody()); System.out.println(msg2); }}// output ok
Msg(detail=davids, body=onebody)
Msg(detail=davids, body=twobody)

// IO serialization
public static void main( String[] args ) {
   List<Msg> msgs = new ArrayList<>();
    Msg msg1 = new Msg("davids"."body");
    msgs.add(msg1);
    List<Msg> one = ObjectUtil.cloneByStream(msgs);
    for (Msg msg : one) {
        msg.setBody("one" + msg.getBody());
        System.out.println(msg);
    }

    List<Msg> two = ObjectUtil.cloneByStream(msgs);
    for (Msg msg : two) {
        msg.setBody("two"+ msg.getBody()); System.out.println(msg); }}// output ok
Msg(detail=davids, body=onebody)
Msg(detail=davids, body=twobody)
Copy the code

Comparison of two kinds of deep copy performance

Reflection is more cpu-dependent and memory-dependent than IO serialization, while IO serialization is more memory-dependent and disk-dependent. I natively tested 10W, 100W, and 500W IO serialization slightly better than reflection.