Understanding Java Deep Copy: Principles and Example

Отвечено с помощью: GPT-4o-mini отJava Q&A Hub

Вопрос:

Java deep copy, please explain the principle and give an example, I need a detailed interpretation

Ответ:

In Java, a deep copy refers to the process of creating a new object that is a copy of an existing object, along with all the objects referenced by it. This means that not only the original object is duplicated, but also all the objects that are referenced by it, recursively. This is in contrast to a shallow copy, where only the top-level object is copied, and the references to the nested objects are shared between the original and the copied object.

Principle of Deep Copy

  1. Object Duplication: A deep copy creates a new instance of the object being copied.
  2. Recursive Copying: For each field in the object that is a reference to another object, a new instance of that referenced object is created, and the reference in the new object points to this new instance.
  3. Independence: The original and the copied object are completely independent. Changes made to the copied object do not affect the original object and vice versa.

Example of Deep Copy

Let's consider a simple example with a Person class that contains a Name class. The Person class has a reference to a Name object. We will implement a deep copy method for the Person class.

class Name {
    private String firstName;
    private String lastName;

    public Name(String firstName, String lastName) {
        this.firstName = firstName;
        this.lastName = lastName;
    }

    // Getters
    public String getFirstName() {
        return firstName;
    }

    public String getLastName() {
        return lastName;
    }

    // Method to create a deep copy of Name
    public Name deepCopy() {
        return new Name(this.firstName, this.lastName);
    }
}

class Person {
    private String id;
    private Name name;

    public Person(String id, Name name) {
        this.id = id;
        this.name = name;
    }

    // Getters
    public String getId() {
        return id;
    }

    public Name getName() {
        return name;
    }

    // Method to create a deep copy of Person
    public Person deepCopy() {
        // Create a new Person object with a deep copy of the Name object
        return new Person(this.id, this.name.deepCopy());
    }
}

public class DeepCopyExample {
    public static void main(String[] args) {
        // Create an original Person object
        Name originalName = new Name("John", "Doe");
        Person originalPerson = new Person("1", originalName);

        // Create a deep copy of the original Person
        Person copiedPerson = originalPerson.deepCopy();

        // Modify the copied Person's name
        copiedPerson.getName().getFirstName(); // This will not affect the original

        // Print original and copied Person details
        System.out.println("Original Person: " + originalPerson.getName().getFirstName() + " " + originalPerson.getName().getLastName());
        System.out.println("Copied Person: " + copiedPerson.getName().getFirstName() + " " + copiedPerson.getName().getLastName());
    }
}

Explanation of the Example

  1. Classes: We have two classes, Name and Person. The Name class has two fields: firstName and lastName. The Person class has an id and a reference to a Name object.

  2. Deep Copy Method:

    • In the Name class, we have a deepCopy method that creates a new Name object with the same firstName and lastName.
    • In the Person class, the deepCopy method creates a new Person object, passing the id and a deep copy of the Name object.
  3. Usage: In the main method, we create an instance of Person and then create a deep copy of it. The original and copied Person objects are independent. If we modify the Name of the copied Person, it does not affect the Name of the original Person.

Conclusion

Deep copying is essential when you want to ensure that changes to a copied object do not affect the original object, especially when dealing with complex objects that contain references to other objects. This is particularly important in scenarios involving mutable objects, where shared references can lead to unintended side effects.