0
0
Lập trình
NM

So Sánh Shallow Copy và Deep Copy trong Java và Python

Đăng vào 8 tháng trước

• 5 phút đọc

So Sánh Shallow Copy và Deep Copy trong Java và Python

Khi làm việc với các đối tượng trong Java hoặc Python, một trong những khái niệm khó khăn nhất là sự khác biệt giữa shallow copydeep copy. Cả hai ngôn ngữ đều truyền tham chiếu đến các đối tượng, điều này có nghĩa là nếu bạn không cẩn thận, các "bản sao" của bạn có thể không độc lập như bạn nghĩ.

Trong bài viết này, chúng ta sẽ phân tích sự khác biệt với ví dụ rõ ràng trong JavaPython.

🔹 Shallow Copy là gì?

Một shallow copy tạo ra một đối tượng mới, nhưng chỉ sao chép cấu trúc cấp cao. Nếu đối tượng chứa các đối tượng khác (danh sách, bản đồ, đối tượng tùy chỉnh), những đối tượng này không được nhân bản — cả hai bản sao vẫn trỏ đến những đối tượng lồng nhau giống nhau.

👉 Việc thay đổi một đối tượng lồng nhau trong một bản sao sẽ ảnh hưởng đến bản sao còn lại.

✅ Shallow Copy trong Java

Dưới đây là ví dụ về shallow copy trong Java:

java Copy
import java.util.*;

class Person implements Cloneable {
    String name;
    List<String> hobbies;

    Person(String name, List<String> hobbies) {
        this.name = name;
        this.hobbies = hobbies;
    }

    // Shallow copy
    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
}

public class Main {
    public static void main(String[] args) throws CloneNotSupportedException {
        List<String> hobbies = new ArrayList<>(Arrays.asList("Cricket", "Chess"));
        Person p1 = new Person("John", hobbies);

        Person p2 = (Person) p1.clone(); // shallow copy

        p2.hobbies.add("Football");

        System.out.println("p1 hobbies: " + p1.hobbies);
        System.out.println("p2 hobbies: " + p2.hobbies);
    }
}

Kết quả:

Copy
p1 hobbies: [Cricket, Chess, Football]
p2 hobbies: [Cricket, Chess, Football]

Cả hai đối tượng chia sẻ cùng một tham chiếu danh sách.

✅ Shallow Copy trong Python

Dưới đây là ví dụ về shallow copy trong Python:

python Copy
import copy

p1 = {"name": "John", "hobbies": ["Cricket", "Chess"]}
p2 = copy.copy(p1)  # shallow copy

p2["hobbies"].append("Football")

print("p1 hobbies:", p1["hobbies"])
print("p2 hobbies:", p2["hobbies"])

Kết quả:

Copy
p1 hobbies: ['Cricket', 'Chess', 'Football']
p2 hobbies: ['Cricket', 'Chess', 'Football']

Hành vi tương tự như Java — shallow copy vẫn chia sẻ danh sách bên trong.

🔹 Deep Copy là gì?

Một deep copy sao chép không chỉ đối tượng mà còn tất cả các đối tượng mà nó tham chiếu. Bản sao là hoàn toàn độc lập — việc thay đổi một không ảnh hưởng đến cái còn lại.

✅ Deep Copy trong Java

Dưới đây là ví dụ về deep copy trong Java:

java Copy
import java.util.*;

class Person implements Cloneable {
    String name;
    List<String> hobbies;

    Person(String name, List<String> hobbies) {
        this.name = name;
        this.hobbies = hobbies;
    }

    // Deep copy
    @Override
    protected Object clone() throws CloneNotSupportedException {
        Person cloned = (Person) super.clone();
        cloned.hobbies = new ArrayList<>(this.hobbies); // sao chép danh sách riêng biệt
        return cloned;
    }
}

public class Main {
    public static void main(String[] args) throws CloneNotSupportedException {
        List<String> hobbies = new ArrayList<>(Arrays.asList("Cricket", "Chess"));
        Person p1 = new Person("John", hobbies);

        Person p2 = (Person) p1.clone(); // deep copy

        p2.hobbies.add("Football");

        System.out.println("p1 hobbies: " + p1.hobbies);
        System.out.println("p2 hobbies: " + p2.hobbies);
    }
}

Kết quả:

Copy
p1 hobbies: [Cricket, Chess]
p2 hobbies: [Cricket, Chess, Football]

Bây giờ các danh sách là độc lập.

✅ Deep Copy trong Python

Dưới đây là ví dụ về deep copy trong Python:

python Copy
import copy

p1 = {"name": "John", "hobbies": ["Cricket", "Chess"]}
p2 = copy.deepcopy(p1)  # deep copy

p2["hobbies"].append("Football")

print("p1 hobbies:", p1["hobbies"])
print("p2 hobbies:", p2["hobbies"])

Kết quả:

Copy
p1 hobbies: ['Cricket', 'Chess']
p2 hobbies: ['Cricket', 'Chess', 'Football']

Ở đây cũng vậy, danh sách bên trong được sao chép độc lập.

🔹 So sánh Nhanh Shallow Copy và Deep Copy

Tính năng Shallow Copy 🟡 Deep Copy 🟢
Sao chép đối tượng chính? ✅ Có ✅ Có
Sao chép đối tượng lồng nhau? ❌ Không (chung) ✅ Có
Thay đổi đối tượng lồng nhau ảnh hưởng đến gốc? ✅ Có ❌ Không
Ví dụ trong Java super.clone() new ArrayList<>(field)
Ví dụ trong Python copy.copy() copy.deepcopy()

🔹 Phân Tích Thực Tế

  • Shallow Copy: Bạn photocopy một báo cáo, nhưng cả hai bản sao đều tham chiếu đến cùng một tệp phụ lục ngoài. Nếu ai đó chỉnh sửa phụ lục, cả hai báo cáo đều bị ảnh hưởng.
  • Deep Copy: Bạn photocopy báo cáo và cũng nhân bản phụ lục. Mỗi báo cáo là hoàn toàn độc lập.

🔹 Những Điều Cần Lưu Ý

  • Trong Java, super.clone() → shallow copy; bạn phải nhân bản các trường có thể thay đổi bằng tay cho deep copy.
  • Trong Python, copy.copy() → shallow copy; copy.deepcopy() → deep copy.
  • Nếu đối tượng của bạn chỉ chứa dữ liệu không thay đổi (như số nguyên, chuỗi), shallow copy thường là đủ.
  • Nếu đối tượng của bạn chứa các cấu trúc dữ liệu có thể thay đổi (danh sách, dict, bản đồ), bạn thường muốn một deep copy.

🔹 Câu Hỏi Thường Gặp

Shallow Copy có an toàn không?

Shallow copy không an toàn khi bạn cần độc lập giữa các đối tượng, vì thay đổi ở bản sao này có thể ảnh hưởng đến bản sao khác.

Làm thế nào để kiểm tra một đối tượng có phải là bản sao sâu hay không?

Bạn có thể kiểm tra xem các thuộc tính của đối tượng có tham chiếu đến cùng một đối tượng hay không, điều này cho thấy đó là shallow copy.

Bài viết này giúp bạn hiểu sâu về sự khác biệt giữa shallow copy và deep copy, từ đó áp dụng chính xác trong lập trình Java và Python.

Gợi ý câu hỏi phỏng vấn
Không có dữ liệu

Không có dữ liệu

Bài viết được đề xuất
Bài viết cùng tác giả

Bình luận

Chưa có bình luận nào

Chưa có bình luận nào