Trong Java, khái niệm immutable dùng để chỉ những class mà đối tượng của chúng không bị thay đổi thông tin sau khi được khởi tạo.
Bình thường, để khai báo một immutable class, chúng ta sẽ:
Khai báo class này là final để không class nào extend được từ nó.
- Khai báo các fields của class đó là private và final,
- Không có các phương thức Setter mà chỉ có các phương thức Getter,
- Nếu một trong các fields của class đó là object thì khi lấy thông tin của field đó, chúng ta cần return copy của object đó.
Ví dụ, nếu mình cần implement class Student với 2 thuộc tính là tên và tuổi, là immutable class, mình sẽ khai báo như sau:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
package com.huongdanjava.javaexample; public final class Student { private final String name; private final int age; public Student(String name, int age) { this.name = name; this.age = age; } public String getName() { return name; } public int getAge() { return age; } } |
Mình đã giới thiệu với các bạn về Project Lombok, về lợi ích của nó trong việc giảm thiểu việc viết code cho những phương thức Getter, hay constructor, … khi khai báo một class. Với immutable class Student ở trên, chúng ta có thể viết lại với Project Lombox như sau:
1 2 3 4 5 6 7 8 9 10 11 12 |
package com.huongdanjava.javaexample; import lombok.AllArgsConstructor; import lombok.Getter; @Getter @AllArgsConstructor public final class Student { private final String name; private final int age; } |
Từ Java 14 trở đi, chúng ta có thể làm điều này nhanh hơn rất nhiều, đơn giản hơn rất nhiều, không cần sử dụng Project Lombok nữa, bằng cách sử dụng từ khoá record khi khai báo class. Giờ thì chúng ta chỉ cần 1 dòng code để implement immutable class Student ở trên, như sau:
1 2 3 |
package com.huongdanjava.javaexample; public record Student(String name, int age) {} |
Java compiler sẽ generate các private, final fields, public constructor với đầy đủ các fields (constructor này còn được gọi là canonical constructor), các phương thức Getter cho những field này, phương thức equals(), phương thức hashCode() và phương thức toString() khi chúng ta sử dụng record để khai báo một class. Đối tượng của những class này sẽ là các đối tượng immutable các bạn nhé!
Giờ thì các bạn có thể khởi tạo và lấy thông tin của một đối tượng Student như sau:
Chúng ta không thể extend class Student này:
bởi vì class Student này là final class.
Các bạn có thể khai báo thêm các constructor khác cho class Student này theo nhu cầu của mình, ví dụ như default constructor hay constructor có 1 tham số, như sau:
1 2 3 4 5 6 7 8 9 10 11 12 |
package com.huongdanjava.javaexample; public record Student(String name, int age) { public Student() { this("Khanh", 35); } public Student(String name) { this(name, 0); } } |
Chúng ta cũng có thể khai báo các static variable và static method bên trong một record class:
1 2 3 4 5 6 7 8 9 10 |
package com.huongdanjava.javaexample; public record Student(String name, int age) { public static String NAME = "Huong Dan Java"; public static void doSomething() { System.out.println("Hello"); } } |
và gọi đến chúng, ví dụ như sau: