Tích hợp xử lý ngoại lệ
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 82 trên 87.
Thử thách
DễHãy làm cho Hệ thống quản lý thư viện của bạn vững chắc hơn bằng cách tích hợp xử lý ngoại lệ phù hợp! Một hệ thống thư viện thực tế cần xử lý ổn thỏa các tình huống lỗi: điều gì xảy ra khi ai đó cố mượn một cuốn sách không tồn tại, hoặc khi người dùng cố mượn nhiều sách hơn số lượng cho phép? Bạn sẽ tạo các ngoại lệ tùy chỉnh để đưa ra phản hồi hữu ích cho những tình huống này.
Bạn sẽ tiếp tục xây dựng dựa trên code hiện có trong sáu tệp:
Book.java: Giữ lớp Book với mọi chức năng hiện có: isbn, title, author, isAvailable, borrowedBy, getDetails() và các hàm getter/setter phù hợp.User.java: Giữ lớp User với id, name, ArrayList borrowedBooks, borrowBook(), returnBook(), getBorrowedCount() và toString().LibraryException.java: Tạo một lớp ngoại lệ tùy chỉnh cơ sở có tênLibraryException, kế thừa từException. Đây sẽ là lớp cha của mọi ngoại lệ dành riêng cho thư viện. Thêm hàm khởi tạo nhận một thông báo và truyền thông báo đó cho lớp cha.BookNotAvailableException.java: Tạo một ngoại lệ tùy chỉnh kế thừa từLibraryException. Ngoại lệ này cần được ném ra khi ai đó cố mượn một cuốn sách đã được mượn. Thêm hàm khởi tạo nhận ISBN của sách và tạo thông báo rõ ràng nhưBook not available: [isbn].Library.java: Cập nhật lớp Library để ném ngoại lệ thay vì in thông báo lỗi. Sửa phương thứcborrowBook(String userId, String isbn)để:- Ném
LibraryExceptionvới thông báoUser not found: [userId]nếu người dùng không tồn tại - Ném
LibraryExceptionvới thông báoBook not found: [isbn]nếu sách không tồn tại - Ném
BookNotAvailableExceptionnếu sách đã được mượn - Nếu thành công, cho người dùng mượn sách và trả về thông báo xác nhận
[userName] borrowed [bookTitle]
Đổi chữ ký phương thức thành
throws LibraryExceptionvà đổi kiểu trả về thànhString.Để các phương thức khác (addBook, registerUser, findBookByIsbn, findUserById, returnBook, removeBook, searchByTitle, searchByAuthor, getAvailableBooks) tiếp tục hoạt động như trước.
- Ném
Main.java: Hãy minh họa cách xử lý ngoại lệ! Bạn sẽ nhận một chuỗi lệnh phân tách bằng dấu phẩy. Mỗi lệnh có một trong các định dạng sau:ADD_BOOK:isbn:title:authorREGISTER_USER:id:nameBORROW:userId:isbn
Xử lý từng lệnh. Với ADD_BOOK, in ra
Added: [title]. Với REGISTER_USER, in raRegistered: [name]. Với các lệnh BORROW, dùng khối try-catch để xử lý ngoại lệ. Nếu thành công, in thông báo xác nhận; nếu xảy ra bất kỳLibraryExceptionnào, in raError: [exception message].Sau khi xử lý mọi lệnh, in ra
Operations completed.
Bạn sẽ nhận một đầu vào: chuỗi lệnh phân tách bằng dấu phẩy.
Ví dụ, với đầu vào ADD_BOOK:ISBN-001:Clean Code:Robert Martin,REGISTER_USER:U001:Alice,BORROW:U001:ISBN-001,BORROW:U001:ISBN-001,BORROW:U002:ISBN-001, đầu ra sẽ là:
Added: Clean Code
Registered: Alice
Alice borrowed Clean Code
Error: Book not available: ISBN-001
Error: User not found: U002
Operations completedLưu ý cách các ngoại lệ tùy chỉnh đưa ra thông báo lỗi rõ ràng, cụ thể. Lần mượn đầu tiên thành công, lần thứ hai thất bại vì sách đã được mượn (BookNotAvailableException), còn lần thứ ba thất bại vì người dùng U002 không tồn tại (LibraryException). Cách làm này giúp hệ thống thư viện cung cấp nhiều thông tin hơn và dễ gỡ lỗi hơn so với các thông báo lỗi chung chung!
Tự làm thử
import java.util.Scanner;
import java.util.ArrayList;
class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
// Đọc các lệnh được phân tách bằng dấu phẩy
String input = scanner.nextLine();
String[] commands = input.split(",");
// Tạo Library và AdminService
Library library = new Library();
AdminService adminService = new AdminService(library);
// Xử lý từng lệnh
for (String command : commands) {
String[] parts = command.split(":");
String operation = parts[0];
if (operation.equals("ADD_BOOK")) {
String isbn = parts[1];
String title = parts[2];
String author = parts[3];
if (adminService.addBook(isbn, title, author)) {
System.out.println("Added: " + title);
}
} else if (operation.equals("REMOVE_BOOK")) {
String isbn = parts[1];
if (adminService.removeBook(isbn)) {
System.out.println("Removed: " + isbn);
} else {
System.out.println("Cannot remove: " + isbn);
}
} else if (operation.equals("REGISTER_USER")) {
String id = parts[1];
String name = parts[2];
if (adminService.registerUser(id, name)) {
System.out.println("Registered: " + name);
}
} else if (operation.equals("BORROW")) {
String userId = parts[1];
String isbn = parts[2];
// TODO: Dùng khối try-catch để gọi library.borrowBook(userId, isbn)
// Nếu thành công, in ra thông báo xác nhận được trả về
// Nếu gặp LibraryException, in ra "Error: " + e.getMessage()
}
}
// TODO: In ra "Operations completed"
}
}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ực13Dự án: Quản lý thư viện
Tổng quan dự án và thiết kế UMLLớp sách và người dùngHệ thống mượn sáchChức năng tìm kiếmGiao diện quản trịTích hợp xử lý ngoại lệKiểm thử và tích hợp2Bộ đ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