Ngoại lệ tùy chỉnh
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 60 trên 87.
Các ngoại lệ có sẵn của Java xử lý nhiều tình huống lỗi phổ biến, nhưng đôi khi bạn cần những ngoại lệ riêng cho lĩnh vực của ứng dụng. Ngoại lệ tùy chỉnh giúp bạn tạo các kiểu lỗi có ý nghĩa, diễn đạt rõ vấn đề đã xảy ra.
Để tạo ngoại lệ tùy chỉnh, bạn chỉ cần kế thừa từ một lớp ngoại lệ hiện có. Với ngoại lệ đã kiểm tra (checked exception), hãy kế thừa từ Exception:
public class InsufficientFundsException extends Exception {
public InsufficientFundsException(String message) {
super(message);
}
}Với ngoại lệ không cần kiểm tra, hãy kế thừa RuntimeException:
public class InvalidAgeException extends RuntimeException {
public InvalidAgeException(String message) {
super(message);
}
}Lời gọi super(message) truyền thông báo lỗi cho lớp cha, giúp bạn có thể truy cập thông báo đó qua getMessage(). Sau đó, bạn có thể ném và bắt ngoại lệ tùy chỉnh như mọi ngoại lệ khác:
public void withdraw(double amount) throws InsufficientFundsException {
if (amount > balance) {
throw new InsufficientFundsException("Balance too low: " + balance);
}
balance -= amount;
}
// Sử dụng phương thức này
try {
account.withdraw(1000);
} catch (InsufficientFundsException e) {
System.out.println(e.getMessage());
}Ngoại lệ tùy chỉnh giúp code dễ đọc hơn và cho phép bên gọi xử lý riêng từng tình huống lỗi cụ thể. Chúng đặc biệt hữu ích khi xây dựng API hoặc thư viện, nơi việc truyền đạt lỗi rõ ràng rất quan trọng.
Thử thách
DễHãy xây dựng một hệ thống đặt vé sử dụng ngoại lệ tùy chỉnh để xử lý các tình huống lỗi khác nhau! Bạn sẽ tạo các kiểu ngoại lệ có ý nghĩa, giúp nêu rõ vấn đề xảy ra khi đặt vé.
Bạn sẽ sắp xếp code trong bốn tệp:
TicketSoldOutException.java: Tạo một ngoại lệ có kiểm tra tùy chỉnh (kế thừaException) cho trường hợp không còn vé. Ngoại lệ của bạn cần nhận một thông báo trong hàm khởi tạo và truyền thông báo đó cho lớp cha bằngsuper(message).InvalidSeatException.java: Tạo một ngoại lệ không kiểm tra tùy chỉnh (kế thừaRuntimeException) cho trường hợp có người cố đặt một số ghế không hợp lệ. Ngoại lệ này cũng cần nhận và truyền thông báo cho lớp cha.TicketBooth.java: Tạo một lớp quản lý việc bán vé. Quầy vé cần theo dõi tổng số ghế còn trống và số ghế hợp lệ lớn nhất. Bao gồm:Một hàm khởi tạo nhận tổng số ghế còn trống.
Một phương thức
bookTicket(int seatNumber)để xác thực việc đặt vé. Nếu không còn vé (số ghế còn trống bằng 0 hoặc nhỏ hơn), hãy ném mộtTicketSoldOutExceptionvới thông báo"No tickets remaining". Nếu số ghế nhỏ hơn 1 hoặc lớn hơn tổng số ghế, hãy ném mộtInvalidSeatExceptionvới thông báo"Seat [seatNumber] does not exist". Nếu không, hãy giảm số ghế còn trống đi 1 và in raBooked seat [seatNumber] successfully.Một phương thức
getAvailableSeats()trả về số ghế còn trống hiện tại.Main.java: Kết hợp các thành phần của hệ thống đặt vé! Bạn sẽ nhận hai đầu vào: tổng số ghế và số ghế cần đặt.Tạo một
TicketBoothvới tổng số ghế đã cho. Sau đó, thử đặt số ghế đã chỉ định bên trong khối try-catch. VìTicketSoldOutExceptionlà ngoại lệ có kiểm tra, bạn phải xử lý nó. BắtTicketSoldOutExceptiontrước và in raBooking failed: [exception message]. Sau đó, bắtInvalidSeatExceptionvà in ra cùng định dạng:Booking failed: [exception message].Sau khối try-catch, hãy in ra
Remaining seats: [count]bằng phương thức getter.
Bạn sẽ nhận hai đầu vào theo thứ tự: tổng số ghế (số nguyên) và số ghế cần đặt (số nguyên).
Hãy chú ý cách ngoại lệ có kiểm tra buộc bên gọi phải xử lý chúng (bằng try-catch hoặc throws), còn ngoại lệ không kiểm tra thì không yêu cầu xử lý tường minh. Hãy chọn kiểu ngoại lệ dựa trên việc bên gọi có nên dự đoán và khắc phục lỗi đó hay không!
Tự làm thử
import java.util.Scanner;
class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int totalSeats = scanner.nextInt();
int seatNumber = scanner.nextInt();
// TODO: Tạo TicketBooth với tổng số ghế đã cho
// TODO: Dùng khối try-catch để thử đặt ghế
// Trước tiên, bắt ngoại lệ (exception) TicketSoldOutException và in ra "Booking failed: [exception message]"
// Bắt InvalidSeatException và in ra "Booking failed: [exception message]"
// TODO: Sau khối try-catch, in ra "Remaining seats: [count]"
}
}
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ỉnh10Xử lý ngoại lệ trong OOP
Phân cấp lớp ngoại lệNgoại lệ tùy chỉnhLỗi có kiểm tra và không kiểm traMẫu try-with-resourcesÔn tập: người dùng đã xác thực2Bộ đ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