Từ khóa final
Thuộc phần Lập trình hướng đối tượng trong hành trình Java của Coddy. Bài học 13 trên 87.
Từ khóa final trong Java ngăn việc sửa đổi. Từ khóa này có thể áp dụng cho biến, phương thức và lớp, mỗi trường hợp có tác dụng khác nhau.
Khi áp dụng cho một biến, final biến nó thành hằng số, sau khi được gán một lần, giá trị của nó không thể thay đổi:
public class Circle {
private final double PI = 3.14159;
private final double radius;
public Circle(double radius) {
this.radius = radius; // Chỉ có thể gán một lần trong hàm khởi tạo (constructor)
}
public void setRadius(double r) {
// this.radius = r; // Lỗi! Không thể gán lại biến (variable) final
}
}Biến final phải được khởi tạo ngay khi khai báo hoặc trong hàm khởi tạo. Sau đó, mọi nỗ lực gán lại giá trị cho biến này đều gây ra lỗi biên dịch.
Với kiểu tham chiếu, final có nghĩa là tham chiếu không thể trỏ đến một đối tượng khác, nhưng nội dung của đối tượng vẫn có thể thay đổi:
private final StringBuilder name = new StringBuilder("John");
// name = new StringBuilder("Jane"); // Lỗi! Không thể gán lại
name.append(" Doe"); // Được! Nội dung của đối tượng có thể thay đổiDùng final với các trường giúp thể hiện ý định rõ ràng: điều này cho các nhà phát triển khác biết rằng giá trị này không bao giờ được thay đổi sau khi khởi tạo. Cách này đặc biệt hữu ích với các giá trị cấu hình, ID hoặc dữ liệu cần giữ nguyên trong suốt vòng đời của một đối tượng.
Không thể ghi đè một phương thức final trong lớp con:
class Base {
public final void greet() {
System.out.println("Hi");
}
}
class Child extends Base {
// public void greet() { } // Lỗi! greet() là final trong Base
}Một final lớp thì hoàn toàn không thể được mở rộng. String là một lớp final, vì vậy không lớp nào có thể mở rộng lớp này:
final class Config { }
// class MyConfig extends Config { } // Lỗi! Config là lớp finalThử thách
DễHãy xây dựng hệ thống đăng ký Student dùng từ khóa final để bảo vệ dữ liệu không bao giờ được thay đổi sau khi đăng ký học sinh.
Bạn sẽ tạo hai tệp để sắp xếp code:
Student.java: Tạo lớp Student có một số thông tin bị khóa vĩnh viễn sau khi thiết lập:- Thuộc tính
finalstudentId(String), được gán khi khởi tạo và không bao giờ thay đổi - Thuộc tính
finalenrollmentYear(int), là năm học sinh đăng ký, cũng không thay đổi - Thuộc tính riêng tư thông thường
name(String), có thể cập nhật nếu học sinh đổi tên - Một hàm khởi tạo nhận cả ba giá trị và khởi tạo các thuộc tính
- Một hàm getter
getStudentId()để lấy mã học sinh - Một hàm getter
getEnrollmentYear()để lấy năm đăng ký - Một hàm getter
getName()và hàm settersetName()để lấy và cập nhật tên - Một phương thức
getInfo()trả về:"ID: [studentId] | Name: [name] | Enrolled: [enrollmentYear]"
- Thuộc tính
Main.java: Tạo một đối tượng Student, sau đó cập nhật tên và hiển thị thông tin. Bạn sẽ nhận bốn đầu vào: mã học sinh, tên ban đầu, năm đăng ký và tên mới cần cập nhật. In ra hai dòng:- Thông tin học sinh trước khi đổi tên
- Thông tin học sinh sau khi đổi tên
Bạn sẽ nhận lần lượt bốn đầu vào: studentId (String), name (String), enrollmentYear (int) và newName (String).
Lưu ý cách các thuộc tính final bảo vệ mã học sinh và năm đăng ký, đây là những hồ sơ cố định không nên thay đổi, còn tên có thể cập nhật bằng hàm setter.
Tự làm thử
import java.util.Scanner;
class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
// Đọc các giá trị đầu vào
String studentId = scanner.nextLine();
String name = scanner.nextLine();
int enrollmentYear = scanner.nextInt();
scanner.nextLine(); // Đọc bỏ ký tự xuống dòng
String newName = scanner.nextLine();
// TODO: Tạo đối tượng Student với các giá trị ban đầu
// TODO: In ra thông tin sinh viên trước khi đổi tên
// TODO: Cập nhật tên sinh viên bằng phương thức setter
// TODO: In ra thông tin sinh viên sau khi đổi tên
}
}
Bài học này có một bài trắc nghiệm ngắn. Bắt đầu bài học để trả lời và theo dõi tiến độ.
Tất cả bài học trong Lập trình hướng đối tượng
1Kiến thức cơ bản về lập trình hướng đối tượng
Tệp bên ngoàiGiới thiệu về lập trình hướng đối tượngLớp và đối tượngTừ khóa thisPhương thứcTrường (thuộc tính)Phương thức khởi tạoNạp chồng phương thức khởi tạoÔn tập: Máy tính đơn giản4Kế thừa
Kế thừa cơ bản (extends)Từ khóa superGhi đè phương thức (@Override)Chuỗi gọi hàm khởi tạoLớp ObjectKế thừa đơn và đa cấpVì sao không hỗ trợ kế thừa nhiều lớpÔn tập: Phân cấp lớp Employee7Phương thức đặc biệt và lớp Object
Phương thức toString()equals() và hashCode()Phương thức clone()compareTo() và ComparableGiao diện ComparatorÔn tập: sắp xếp tùy chỉnh2Bộ điều chỉnh quyền truy cập và đóng gói
Tổng quan về các mức truy cậpPhương thức getter và setterẨn thông tinTừ khóa finalÔn tập: Trình quản lý tài khoản ngân hàng5Tính đa hình
Kiến thức cơ bản về nạp chồng phương thứcGhi đè phương thức (thời gian chạy)Chuyển kiểu lên và chuyển kiểu xuốngToán tử instanceofLớp và phương thức trừu tượngÔn tập: máy tính hình học8Khái niệm OOP nâng cao
Kết hợp và kế thừaKết tập và hợp thànhLớp bên trong, lớp lồng nhau và lớp ẩn danhKiểu enum và phương thức enumBản ghi (Java 16+)Lớp sealed (Java 17+)3Thuộc tính lớp và thành viên tĩnh
Biến của instance và biến tĩnhPhương thức tĩnhKhối tĩnhHằng số (static final)Ôn tập: bộ đếm và tiện ích6Giao diện và lớp trừu tượng
Giới thiệu về giao diệnTriển khai giao diệnTriển khai nhiều giao diệnPhương thức mặc định và tĩnh trong giao diệnLớp trừu tượng và giao diệnGiao diện hàmÔn tập: hệ thống thanh toán9Kiểu tổng quát
Giới thiệu về kiểu tổng quátLớp tổng quátPhương thức tổng quátTham số kiểu có giới hạnKý tự đại diện (?, extends, super)Ôn tập: vùng chứa tổng quát12Mẫu thiết kế, phần 2
Mẫu CommandMẫu AdapterMẫu DecoratorMẫu Template MethodMẫu StateMẫu CompositeMẫu IteratorTự luyện tập: Trình biên dịch Java online