Integração de Tratamento de Exceções
Parte da seção Programação Orientada a Objetos do Journey de Java da Coddy — lição 82 de 87.
Desafio
FácilVamos tornar o seu Sistema de Gerenciamento de Biblioteca mais robusto integrando o tratamento de exceções adequado! Um sistema de biblioteca real precisa lidar graciosamente com condições de erro — o que acontece quando alguém tenta pegar emprestado um livro que não existe, ou quando um usuário tenta pegar mais livros do que o permitido? Você criará exceções personalizadas que fornecem feedback significativo para esses cenários.
Você continuará construindo sobre o seu código existente em seis arquivos:
Book.java: Mantenha sua classe Book com toda a funcionalidade existente — isbn, title, author, isAvailable, borrowedBy, getDetails() e os getters/setters apropriados.User.java: Mantenha sua classe User com id, name, o ArrayList borrowedBooks, borrowBook(), returnBook(), getBorrowedCount() e toString().LibraryException.java: Crie uma classe de exceção personalizada base chamadaLibraryExceptionque estendeException. Esta será a classe pai para todas as exceções específicas da biblioteca. Inclua um construtor que aceite uma mensagem e a passe para a classe pai.BookNotAvailableException.java: Crie uma exceção personalizada que estendeLibraryException. Esta exceção deve ser lançada quando alguém tenta pegar emprestado um livro que já está emprestado. Inclua um construtor que aceite o ISBN do livro e crie uma mensagem significativa comoBook not available: [isbn].Library.java: Atualize sua classe Library para lançar exceções em vez de imprimir mensagens de erro. Modifique o métodoborrowBook(String userId, String isbn)para:- Lançar
LibraryExceptioncom a mensagemUser not found: [userId]se o usuário não existir - Lançar
LibraryExceptioncom a mensagemBook not found: [isbn]se o livro não existir - Lançar
BookNotAvailableExceptionse o livro já estiver emprestado - Em caso de sucesso, faça o usuário pegar o livro emprestado e retorne a mensagem de confirmação
[userName] borrowed [bookTitle]
Altere a assinatura do método para
throws LibraryExceptione altere o tipo de retorno paraString.Mantenha todos os outros métodos (addBook, registerUser, findBookByIsbn, findUserById, returnBook, removeBook, searchByTitle, searchByAuthor, getAvailableBooks) funcionando como antes.
- Lançar
Main.java: Demonstre seu tratamento de exceções! Você receberá uma string de comandos separados por vírgula. Cada comando segue um destes formatos:ADD_BOOK:isbn:title:authorREGISTER_USER:id:nameBORROW:userId:isbn
Processe cada comando. Para ADD_BOOK, imprima
Added: [title]. Para REGISTER_USER, imprimaRegistered: [name]. Para comandos BORROW, use um bloco try-catch para tratar exceções — em caso de sucesso imprima a mensagem de confirmação, em qualquerLibraryExceptionimprimaError: [exception message].Após processar todos os comandos, imprima
Operations completed.
Você receberá uma entrada: uma string de comandos separados por vírgula.
Por exemplo, com a entrada ADD_BOOK:ISBN-001:Clean Code:Robert Martin,REGISTER_USER:U001:Alice,BORROW:U001:ISBN-001,BORROW:U001:ISBN-001,BORROW:U002:ISBN-001, sua saída seria:
Added: Clean Code
Registered: Alice
Alice borrowed Clean Code
Error: Book not available: ISBN-001
Error: User not found: U002
Operations completedObserve como as exceções personalizadas fornecem mensagens de erro claras e específicas. O primeiro empréstimo é bem-sucedido, o segundo falha porque o livro já está emprestado (BookNotAvailableException) e o terceiro falha porque o usuário U002 não existe (LibraryException). Essa abordagem torna seu sistema de biblioteca muito mais informativo e fácil de depurar do que mensagens de erro genéricas!
Experimente você mesmo
import java.util.Scanner;
import java.util.ArrayList;
class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
// Lê os comandos separados por vírgula
String input = scanner.nextLine();
String[] commands = input.split(",");
// Cria Library e AdminService
Library library = new Library();
AdminService adminService = new AdminService(library);
// Processa cada comando
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: Use um bloco try-catch para chamar library.borrowBook(userId, isbn)
// Em caso de sucesso, imprima a mensagem de confirmação retornada
// Em caso de LibraryException, imprima "Error: " + e.getMessage()
}
}
// TODO: Imprima "Operations completed"
}
}Todas as lições de Programação Orientada a Objetos
1Fundamentos de POO
Arquivos ExternosIntrodução à POOClasses vs ObjetosA Palavra-chave thisMétodosCampos (Atributos)Método ConstrutorSobrecarga de ConstrutorRecapitulação - Calculadora Simples4Herança
Herança Básica (extends)A Palavra-chave superSobrescrita de Método (@Override)Encadeamento de ConstrutoresA Classe ObjectHerança Simples e MultinívelPor que não há Herança Múltipla de ClassesRecapitulação - Hierarquia de Funcionários7Métodos Especiais e a Classe Object
Método toString()equals() e hashCode()Método clone()compareTo() e ComparableInterface ComparatorRecapitulação - Ordenação Personalizada10Tratamento de Exceções em POO
Hierarquia de Classes de ExceçãoExceções PersonalizadasErros Checked vs UncheckedPadrão Try With ResourcesRecapitulação - Usuário Validado13Projeto: Gerenciamento de Biblioteca
Visão Geral do Projeto e Modelagem UMLClasses Livro e Usuário2Modificadores de Acesso e Encapsulamento
Visão Geral dos Níveis de AcessoMétodos Getter e SetterOcultação de InformaçõesA Palavra-chave finalRecapitulação - Gerenciador de Conta Bancária5Polimorfismo
Fundamentos de Sobrecarga de MétodosSobrescrita de Métodos (Tempo de Execução)Upcasting e DowncastingO Operador instanceofClasses e Métodos AbstratosRecapitulação - Calculadora de Formas8Conceitos Avançados de OOP
Composição vs HerançaAgregação vs ComposiçãoClasses Internas, Aninhadas e AnônimasEnums e Métodos de EnumRecords (Java 16+)Classes Seladas (Java 17+)11Padrões de Projeto Parte 1
Introdução aos Padrões de ProjetoPadrão SingletonPadrão FactoryPadrão BuilderPadrão ObserverPadrão Strategy3Propriedades de Classe e Membros Estáticos
Variáveis de Instância vs EstáticasMétodos EstáticosBlocos EstáticosConstantes (static final)Recapitulação - Contador e Utilitário6Interfaces e Classes Abstratas
Introdução às InterfacesImplementando InterfacesImplementação de Múltiplas InterfacesDefault e Static em InterfacesClasses Abstratas vs InterfacesInterfaces FuncionaisRecapitulação - Sistema de Pagamento9Generics
Introdução a GenericsClasses GenéricasMétodos GenéricosParâmetros de Tipos DelimitadosWildcards (?, extends, super)Recapitulação - Container Genérico12Padrões de Projeto Parte 2
Padrão CommandPadrão AdapterPadrão DecoratorPadrão Template MethodPadrão StatePadrão CompositePadrão Iterator