An article explaining deep copy, shallow copy and zero copy in Java

Preface

Copying objects is a common operation when writing code in Java. According to the different levels and methods of copying, it can be divided into deep copy, shallow copy and zero copy. In this article, we will introduce in detail the concepts, implementation methods and usage scenarios of these three copy methods to facilitate learning and interviews.

Insert image description here

deep copy

Deep copy is a method of creating a copy of an object where the new object is completely independent of the original object. This means that all fields of the new object are copied, and if the fields are reference types, a deep copy is performed recursively to ensure that the new object and the original object do not share any internal objects.

How to implement deep copy, let’s introduce it next:

  1. Manual implementation: by creating a new object and copying the values ​​of the fields one by one . If the field is a reference type, you need to recursively create a new instance of the field, but this process is more cumbersome.
  2. Use serialization: Serialize the object into a stream of bytes and then deserialize back into a new object . This approach requires that the object and all its components are serializable.
  3. Using clones: Implement the Cloneable interface and override the clone() method . But this approach is controversial because it may not provide a true deep copy unless all relevant classes correctly implement the clone() method.

For example, we now have a simple Person class and an Address class:

class Address implements Serializable {
    
      
    private String street;  
    // ... 其他属性和方法 ...  
}  
  
class Person implements Serializable {
    
      
    private String name;  
    private Address address;  
    // ... 其他属性和方法 ...  
      
    public Person deepCopy() {
    
      
        try {
    
      
            // 使用序列化实现深拷贝  
            ByteArrayOutputStream baos = new ByteArrayOutputStream();  
            ObjectOutputStream oos = new ObjectOutputStream(baos);  
            oos.writeObject(this);  
            oos.close();  
              
            ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());  
            ObjectInputStream ois = new ObjectInputStream(bais);  
            return (Person) ois.readObject();  
        } catch (Exception e) {
    
      
            throw new RuntimeException(e);  
        }  
    }  
}

Code explanation:
It is not difficult to see that the Person class has a field of Address type. We implement the Serializable interface and use serialization and deserialization techniques to create a deep copy of the Person object. This means that the newly created Person object is completely independent from the original object and they do not share any internal state.

Shallow copy

Shallow copy creates a new object and copies all non-static fields of the original object to the new object . However, if the field is a reference type, only the reference is copied and not the referenced object . Therefore, for fields of reference type, the original object and the new object share the same internal object.

So how to implement shallow copy, the method is as follows:

We can usually achieve a shallow copy by creating a new object and using a constructor or setter method to copy the value of the original object into the new object. The autoboxing and unboxing mechanisms in Java simplify copying of basic data types .

Such as:

Using the Person and Address classes above as an example:

class Person {
    
      
    private String name;  
    private Address address;  
    // ... 其他属性和方法 ...  
      
    public Person shallowCopy() {
    
      
        Person copy = new Person();  
        copy.setName(this.name); // 复制基本数据类型字段  
        copy.setAddress(this.address); // 只复制引用,不复制引用的对象  
        return copy;  
    }  
}

To explain the above code:
we create a new Person object and copy the value of the basic data type field and the reference of the reference type field to implement a shallow copy. This means that modifying the name field of the new object will not affect the original object, but modifying the address field of the new object will affect the original object because they share the same Address object.

zero copy

Zero copy is a technology that avoids unnecessary data duplication during data transfer. Zero-copy is often associated with I/O operations, especially when data is moved from one storage location to another. By transferring data directly between memory, files or networks, zero-copy technology can reduce CPU usage and memory bandwidth consumption, thereby improving performance.

Where is zero-copy technology used in Java? for example:

  • MappedByteBuffer: Use a memory-mapped file to map a file or a portion of a file into memory, allowing direct access to file data without the need to copy the data into the application's memory . This can be achieved through the map() method in FileChannel.
  • FileChannel's transferTo/transferFrom methods: These methods allow data to be transferred directly between file channels or socket channels without first copying it into the application's memory. For example, you can use the transferTo() method in FileChannel to send data directly from a file to a network socket.
  • DirectBuffer: By using a direct buffer (DirectBuffer), data can be processed directly in the native memory of the operating system without first being copied to Java heap memory. This can be achieved by creating a ByteBuffer and calling its allocateDirect() method.

For example, the above is Java's NIO library that provides some implementation methods of zero-copy technology.

try (FileChannel sourceChannel = new FileInputStream("source.txt").getChannel();  
     FileChannel destinationChannel = new FileOutputStream("destination.txt").getChannel()) {
    
      
    destinationChannel.transferFrom(sourceChannel, 0, sourceChannel.size());  
} catch (IOException e) {
    
      
    e.printStackTrace();  
}

In the above code, we use the transferFrom() method of FileChannel to implement zero copy of file transfer. Data is transferred directly from the source file channel to the target file channel without first being copied into the application's memory . This approach improves performance and reduces memory consumption when processing large files.

The article ends here. If you are interested, you can subscribe to the column. We will continue to share relevant knowledge points in the future.

Insert image description here

Guess you like

Origin blog.csdn.net/qq_53847859/article/details/135155706