Интеграция обработки исключений
Часть раздела Объектно-ориентированное программирование путешествия по Java на Coddy — урок 82 из 87.
Задание
ЛегкоДавайте сделаем вашу систему управления библиотекой более надежной, интегрировав правильную обработку исключений! Реальная библиотечная система должна изящно обрабатывать ошибочные ситуации — что произойдет, если кто-то попытается взять книгу, которой не существует, или когда пользователь пытается взять больше книг, чем разрешено? Вы создадите пользовательские исключения, которые обеспечат содержательную обратную связь для таких сценариев.
Вы продолжите работу над существующим кодом в шести файлах:
Book.java: Сохраните класс Book со всей существующей функциональностью — isbn, title, author, isAvailable, borrowedBy, getDetails() и соответствующими геттерами/сеттерами.User.java: Сохраните класс User с id, name, списком ArrayList borrowedBooks, методами borrowBook(), returnBook(), getBorrowedCount() и toString().LibraryException.java: Создайте базовый класс пользовательского исключения с именемLibraryException, который расширяетException. Это будет родительский класс для всех специфичных для библиотеки исключений. Включите конструктор, который принимает сообщение и передает его родительскому классу.BookNotAvailableException.java: Создайте пользовательское исключение, которое расширяетLibraryException. Это исключение должно выбрасываться, когда кто-то пытается взять книгу, которая уже выдана. Включите конструктор, который принимает ISBN книги и создает содержательное сообщение, напримерBook not available: [isbn].Library.java: Обновите класс Library, чтобы он выбрасывал исключения вместо вывода сообщений об ошибках. Измените методborrowBook(String userId, String isbn), чтобы он:- Выбрасывал
LibraryExceptionс сообщениемUser not found: [userId], если пользователь не существует - Выбрасывал
LibraryExceptionс сообщениемBook not found: [isbn], если книга не существует - Выбрасывал
BookNotAvailableException, если книга уже выдана - В случае успеха пользователь берет книгу, и метод возвращает подтверждающее сообщение
[userName] borrowed [bookTitle]
Измените сигнатуру метода на
throws LibraryExceptionи измените тип возвращаемого значения наString.Оставьте все остальные методы (addBook, registerUser, findBookByIsbn, findUserById, returnBook, removeBook, searchByTitle, searchByAuthor, getAvailableBooks) работающими как прежде.
- Выбрасывал
Main.java: Продемонстрируйте обработку исключений! Вы получите строку команд, разделенных запятыми. Каждая команда соответствует одному из следующих форматов:ADD_BOOK:isbn:title:authorREGISTER_USER:id:nameBORROW:userId:isbn
Обработайте каждую команду. Для ADD_BOOK выведите
Added: [title]. Для REGISTER_USER выведитеRegistered: [name]. Для команд BORROW используйте блок try-catch для обработки исключений — в случае успеха выведите подтверждающее сообщение, при любомLibraryExceptionвыведитеError: [exception message].После обработки всех команд выведите
Operations completed.
Вы получите один входной параметр: строку команд, разделенных запятыми.
Например, при вводе ADD_BOOK:ISBN-001:Clean Code:Robert Martin,REGISTER_USER:U001:Alice,BORROW:U001:ISBN-001,BORROW:U001:ISBN-001,BORROW:U002:ISBN-001 ваш вывод будет следующим:
Added: Clean Code
Registered: Alice
Alice borrowed Clean Code
Error: Book not available: ISBN-001
Error: User not found: U002
Operations completedОбратите внимание, как пользовательские исключения предоставляют четкие и конкретные сообщения об ошибках. Первая выдача проходит успешно, вторая завершается ошибкой, так как книга уже выдана (BookNotAvailableException), а третья — ошибкой, так как пользователь U002 не существует (LibraryException). Такой подход делает вашу библиотечную систему гораздо более информативной и простой в отладке, чем использование общих сообщений об ошибках!
Попробуйте сами
import java.util.Scanner;
import java.util.ArrayList;
class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
// Прочитать команды, разделенные запятыми
String input = scanner.nextLine();
String[] commands = input.split(",");
// Создать Library и AdminService
Library library = new Library();
AdminService adminService = new AdminService(library);
// Обработать каждую команду
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: Используйте блок try-catch для вызова library.borrowBook(userId, isbn)
// В случае успеха выведите возвращенное подтверждающее сообщение
// При возникновении LibraryException выведите "Error: " + e.getMessage()
}
}
// TODO: Вывести "Operations completed"
}
}Все уроки раздела Объектно-ориентированное программирование
1Основы ООП
Внешние файлыВведение в ООПКлассы и объектыКлючевое слово thisМетодыПоля (атрибуты)Метод-конструкторПерегрузка конструкторовИтоги — Простой калькулятор4Наследование
Основы наследования (extends)Ключевое слово superПереопределение методов (@Override)Цепочка конструкторовКласс ObjectОдиночное и многоуровневое наследованиеПочему нет множественного наследования классовИтоги — Иерархия сотрудников7Специальные методы и класс Object
Метод toString()equals() и hashCode()Метод clone()compareTo() и ComparableИнтерфейс ComparatorПовторение — Кастомная сортировка10Обработка исключений в ООП
Иерархия классов исключенийПользовательские исключенияПроверяемые и непроверяемые ошибкиПаттерн Try With ResourcesПовторение — Validated User13Проект: Управление библиотекой
Обзор проекта и UML-проектированиеКлассы Book и User2Модификаторы доступа и инкапсуляция
Обзор уровней доступаМетоды геттеры и сеттерыСокрытие данныхКлючевое слово finalИтоги — Менеджер банковского счета5Полиморфизм
Основы перегрузки методовПереопределение методов (Run-Time)Upcasting и DowncastingОператор instanceofАбстрактные классы и методыИтоги: Калькулятор фигур8Продвинутые концепции ООП
Композиция против наследованияАгрегация против композицииВнутренние, вложенные и анонимные классыEnums и методы перечисленийRecords (Java 16+)Sealed-классы (Java 17+)11Паттерны проектирования. Часть 1
Введение в паттерны проектированияПаттерн SingletonПаттерн FactoryПаттерн BuilderПаттерн ObserverПаттерн Strategy3Свойства класса и статические члены
Переменные экземпляра и статические переменныеСтатические методыСтатические блокиКонстанты (static final)Итоги: Счетчик и утилиты6Интерфейсы и абстрактные классы
Введение в интерфейсыРеализация интерфейсовРеализация нескольких интерфейсовDefault и Static методы в интерфейсахАбстрактные классы vs ИнтерфейсыФункциональные интерфейсыИтоги — Платежная система9Обобщения
Введение в обобщенияОбобщенные классыОбобщенные методыОграниченные параметры типаСимволы подстановки (Wildcards: ?, extends, super)Итоги — Обобщенный контейнер12Паттерны проектирования. Часть 2
Паттерн «Команда»Паттерн «Адаптер»Паттерн «Декоратор»Паттерн «Шаблонный метод»Паттерн «Состояние»Паттерн «Компоновщик»Паттерн «Итератор»