- Sản phẩm & Dịch vụSản phẩm & Dịch vụ
- Giải phápGiải pháp
- Bảng giáBảng giá
- Công tyCông ty
- Tài liệuTài liệu
vi
vi
Chuyên mục với các bài viết hướng dẫn, nghiên cứu và phân tích chi tiết về kỹ thuật, các xu hướng công nghệ mới nhất dành cho lập trình viên.
Technical Writer
I have over 5 years of experience writing technical documentation for tech products, making them accessible and user-friendly. My focus is always on providing clear and precise information. @#@ Tôi đã có hơn 5 năm kinh nghiệm viết tài liệu kỹ thuật cho các sản phẩm công nghệ, giúp người dùng dễ dàng tiếp cận và sử dụng. Tôi luôn tập trung vào việc cung cấp thông tin chính xác và dễ hiểu.
Thảo luận (0)
Đăng nhập để thảo luận

Bài viết này sẽ cung cấp cho bạn một bức tranh tổng quan về cách tạo một lớp immutable trong Java .
Một đối tượng (object) được coi là bất biến (immutable) khi trạng thái của nó không thay đổi sau khi được khởi tạo. Ví dụ, String là một lớp bất biến, và một khi đã được khởi tạo, giá trị của một object String sẽ không bao giờ thay đổi.
Vì một object bất biến không thể được cập nhật, bạn cần tạo một object mới cho mỗi lần thay đổi trạng thái. Tuy nhiên, các object bất biến cũng mang lại những lợi ích sau:
Để tạo một lớp immutable trong Java, bạn cần tuân thủ các nguyên tắc chung sau:
final: Điều này ngăn không cho bất kỳ lớp nào khác kế thừa (extend) nó.private: Để không ai có thể truy cập và thay đổi giá trị trực tiếp từ bên ngoài.final: Đảm bảo rằng giá trị của một trường chỉ được gán duy nhất một lần.Lớp sau đây là một ví dụ minh họa các nguyên tắc cơ bản của tính bất biến.
Lớp FinalClassExample định nghĩa các trường và cung cấp phương thức khởi tạo sử dụng sao chép sâu để khởi tạo object. Đoạn code trong phương thức main của tệp FinalClassExample.java kiểm tra tính bất biến của object.
Tạo một tệp mới có tên FinalClassExample.java và sao chép đoạn code sau:
FinalClassExample.java
`import java.util.HashMap; import java.util.Iterator;
public final class FinalClassExample { // [cite: 21] // fields of the FinalClassExample class private final int id; // [cite: 22] private final String name; // [cite: 22] private final HashMap<String, String> testMap; // [cite: 22]
public int getId() { // [cite: 22]
return id;
}
public String getName() { // [cite: 23]
return name;
}
// Getter function for mutable objects
public HashMap<String, String> getTestMap() { // [cite: 25]
return (HashMap<String, String>) testMap.clone(); // [cite: 25]
}
// Constructor method performing deep copy
public FinalClassExample(int i, String n, HashMap<String, String> hm) { // [cite: 26]
System.out.println("Performing Deep Copy for Object initialization"); // [cite: 26]
// "this" keyword refers to the current object
this.id = i; // [cite: 26]
this.name = n; // [cite: 26]
HashMap<String, String> tempMap = new HashMap<String, String>(); // [cite: 27]
String key; // [cite: 27]
Iterator<String> it = hm.keySet().iterator(); // [cite: 27]
while (it.hasNext()) { // [cite: 27]
key = it.next(); // [cite: 27]
tempMap.put(key, hm.get(key)); // [cite: 27]
}
this.testMap = tempMap; // [cite: 27]
}
// Test the immutable class
public static void main(String[] args) { // [cite: 28]
HashMap<String, String> h1 = new HashMap<String, String>(); // [cite: 28]
h1.put("1", "first"); // [cite: 28]
h1.put("2", "second"); // [cite: 28]
String s = "original"; // [cite: 28]
int i = 10; // [cite: 28]
FinalClassExample ce = new FinalClassExample(i, s, h1); // [cite: 29]
// print the ce values
System.out.println("ce id: " + ce.getId()); // [cite: 30]
System.out.println("ce name: " + ce.getName()); // [cite: 30]
System.out.println("ce testMap: " + ce.getTestMap()); // [cite: 30]
// change the local variable values
i = 20; // [cite: 30]
s = "modified"; // [cite: 30]
h1.put("3", "third"); // [cite: 32]
// print the values again
System.out.println("ce id after local variable change: " + ce.getId()); // [cite: 32]
System.out.println("ce name after local variable change: " + ce.getName()); // [cite: 32]
System.out.println("ce testMap after local variable change: " + ce.getTestMap()); // [cite: 32]
HashMap<String, String> hmTest = ce.getTestMap(); // [cite: 32]
hmTest.put("4", "new"); // [cite: 32]
System.out.println("ce testMap after changing variable from getter method: " + ce.getTestMap()); // [cite: 32]
}
}`
Biên dịch và chạy chương trình:
$ javac FinalClassExample.java $ java FinalClassExample
Lưu ý: Bạn có thể nhận được thông báo sau khi biên dịch tệp như sau: FinalClassExample.java uses unchecked or unsafe operations because the getter method is using an unchecked cast from HashMap<String, String> to Object Với ví dụ này, bạn cứ yên tâm bỏ qua cảnh báo của trình biên dịch nhé.
Bạn sẽ nhận được kết quả sau:
Output
Performing Deep Copy for Object initialization ce id: 10 ce name: original ce testMap: {1=first, 2=second} ce id after local variable change: 10 ce name after local variable change: original ce testMap after local variable change: {1=first, 2=second} ce testMap after changing variable from getter methods: {1=first, 2=second}
Đầu ra cho thấy các giá trị của HashMap không thay đổi vì hàm tạo sử dụng sao chép sâu và hàm getter trả về một bản sao của object gốc.
Bạn có thể thay đổi tệp FinalClassExample.java để xem điều gì xảy ra khi bạn sử dụng sao chép nông (shallow copy) thay vì sao chép sâu và trả về object thay vì một bản sao. Object sẽ không còn bất biến và có thể bị thay đổi. Thử thay đổi tệp ví dụ như sau (hoặc sao chép và dán đoạn code mẫu):
return (HashMap<String, String>) testMap.clone(); và thêm return testMap;.Tệp ví dụ của bạn sẽ có dạng như thế này:
FinalClassExample.java
`import java.util.HashMap; import java.util.Iterator;
public final class FinalClassExample { // [cite: 43] // fields of the FinalClassExample class private final int id; // [cite: 44] private final String name; // [cite: 44] private final HashMap<String, String> testMap; // [cite: 44]
public int getId() { // [cite: 44]
return id;
}
public String getName() { // [cite: 45]
return name;
}
// Getter function for mutable objects
public HashMap<String, String> getTestMap() { // [cite: 45]
return testMap; // [cite: 47]
}
//Constructor method performing shallow copy
public FinalClassExample(int i, String n, HashMap<String, String> hm) { // [cite: 47]
System.out.println("Performing Shallow Copy for Object initialization"); // [cite: 47]
this.id = i; // [cite: 48]
this.name = n; // [cite: 48]
this.testMap = hm; // [cite: 48]
}
// Test the immutable class
public static void main(String[] args) { // [cite: 49]
HashMap<String, String> h1 = new HashMap<String, String>(); // [cite: 49]
h1.put("1", "first"); // [cite: 49]
h1.put("2", "second"); // [cite: 49]
String s = "original"; // [cite: 49]
int i = 10; // [cite: 49]
FinalClassExample ce = new FinalClassExample(i, s, h1); // [cite: 49]
// print the ce values.
System.out.println("ce id: " + ce.getId()); // [cite: 50]
System.out.println("ce name: " + ce.getName()); // [cite: 50]
System.out.println("ce testMap: " + ce.getTestMap()); // [cite: 50]
// change the local variable values
i = 20; // [cite: 50]
s = "modified"; // [cite: 50]
h1.put("3", "third"); // [cite: 50]
// print the values again
System.out.println("ce id after local variable change: " + ce.getId()); // [cite: 50]
System.out.println("ce name after local variable change: " + ce.getName()); // [cite: 50]
System.out.println("ce testMap after local variable change: " + ce.getTestMap()); // [cite: 50]
HashMap<String, String> hmTest = ce.getTestMap(); // [cite: 50]
hmTest.put("4", "new"); // [cite: 50]
System.out.println("ce testMap after changing variable from getter method: " + ce.getTestMap()); // [cite: 50]
}
}`
Biên dịch và chạy chương trình:
javac FinalClassExample.javajava FinalClassExample
Bạn sẽ nhận được output sau:
Output
Performing Shallow Copy for Object initialization ce id: 10 ce name: original ce testMap: {1=first, 2=second} ce id after local variable change: 10 ce name after local variable change: original ce testMap after local variable change: {1=first, 2=second, 3=third} ce testMap after changing variable from getter methods: {1=first, 2=second, 3=third, 4=new}
Output này cho thấy các giá trị của HashMap đã thay đổi. Điều này là do phương thức khởi tạo sử dụng sao chép nông (shallow copy) và có một tham chiếu trực tiếp đến object gốc trong hàm getter.
Bạn đã tìm hiểu một số nguyên tắc chung cần tuân thủ khi tạo một lớp immutable trong Java, bao gồm tầm quan trọng của sao chép sâu (deep copy). Việc tạo các lớp bất biến trong Java là một phương thức giúp nâng cao tính bảo mật, độ tin cậy và khả năng xử lý dễ dàng trong môi trường đa luồng. Bằng cách tuân thủ các nguyên tắc đã trình bày như trên, bạn có thể xây dựng nên một hệ thống ổn định hơn.