Aplicação completa integrando os conceitos do curso
Parabéns por chegar até aqui! Nas próximas três aulas você vai colocar em prática tudo que aprendeu no curso construindo aplicações reais que rodam no seu computador.
Nesta aula, vamos construir um Sistema de Gerenciamento de Biblioteca. O programa permite cadastrar livros, buscar por título ou ISBN, emprestar, devolver e listar o acervo completo — tudo via terminal, com interação real do usuário.
Como rodar no VSCode: Crie um arquivo chamado Biblioteca.java, cole o código completo, abra o terminal integrado do VSCode (Ctrl + `) e execute com javac Biblioteca.java seguido de java Biblioteca.
Antes de ver o código, veja quais aulas do curso estão sendo usadas aqui:
| Conceito | Onde aparece no projeto | Aulas relacionadas |
|---|---|---|
| Classe e objetos | A classe Livro modela cada livro do acervo |
Aulas 64–65 |
| ArrayList | ArrayList<Livro> armazena o acervo dinamicamente |
Aulas 57–59 |
| HashMap | HashMap<String, Livro> permite busca rápida por ISBN |
Aulas 60–61 |
| Scanner | Lê todas as entradas do usuário no menu | Aula 17 |
| Métodos personalizados | cadastrar(), buscar(), emprestar(), devolver(), listar() |
Aulas 34, 48 |
| Loop do-while | Mantém o menu ativo até o usuário escolher sair | Aula 42 |
| Switch-case | Direciona a opção escolhida no menu para o método correto | Aula 45 |
| For-each | Percorre o acervo para listar e buscar livros | Aula 47 |
| boolean | Campo disponivel controla se o livro está emprestado |
Aula 06 |
| Métodos de String | .toLowerCase() torna a busca por título insensível a maiúsculas |
Aula 35 |
O primeiro passo é modelar o que é um livro no nosso sistema. Cada livro tem quatro informações: título, autor, ISBN e disponibilidade. Isso vai para dentro de uma classe:
// A classe Livro representa um único livro do acervo class Livro { String titulo; String autor; String isbn; boolean disponivel; // Construtor: recebe os dados e cria o objeto Livro(String titulo, String autor, String isbn) { this.titulo = titulo; this.autor = autor; this.isbn = isbn; this.disponivel = true; // Todo livro começa disponível } }
O que é this? Dentro do construtor, this.titulo se refere ao campo do objeto, enquanto titulo sozinho se refere ao parâmetro recebido. O this elimina a ambiguidade quando os nomes são iguais.
Cole este código inteiro em um arquivo chamado Biblioteca.java. Cada seção está comentada para facilitar a leitura:
import java.util.ArrayList; import java.util.HashMap; import java.util.Scanner; // ─── Classe que modela um livro ──────────────────────────────────────────── class Livro { String titulo; String autor; String isbn; boolean disponivel; Livro(String titulo, String autor, String isbn) { this.titulo = titulo; this.autor = autor; this.isbn = isbn; this.disponivel = true; } } // ─── Classe principal ───────────────────────────────────────────────────── public class Biblioteca { // Acervo: lista dinâmica de livros static ArrayList<Livro> acervo = new ArrayList<>(); // Índice rápido: ISBN → Livro static HashMap<String, Livro> indiceIsbn = new HashMap<>(); static Scanner sc = new Scanner(System.in); // ── MÉTODO PRINCIPAL ──────────────────────────────────────────────────── public static void main(String[] args) { // Popula o acervo com alguns livros iniciais cadastrar("O Hobbit", "J.R.R. Tolkien", "978-0261102217"); cadastrar("Dom Casmurro", "Machado de Assis", "978-8535910902"); cadastrar("Clean Code", "Robert C. Martin", "978-0132350884"); cadastrar("O Alquimista", "Paulo Coelho", "978-8531608087"); cadastrar("Algoritmos em Java", "Robert Sedgewick", "978-0201361209"); int opcao; do { exibirMenu(); opcao = Integer.parseInt(sc.nextLine().trim()); switch (opcao) { case 1: menuCadastrar(); break; case 2: menuBuscar(); break; case 3: menuEmprestar(); break; case 4: menuDevolver(); break; case 5: listar(); break; case 0: System.out.println("\nAté logo! Biblioteca encerrada."); break; default: System.out.println("Opção inválida. Tente novamente."); } } while (opcao != 0); sc.close(); } // ── MENU ──────────────────────────────────────────────────────────────── static void exibirMenu() { System.out.println("\n╔══════════════════════════════╗"); System.out.println("║ SISTEMA DE BIBLIOTECA ║"); System.out.println("╠══════════════════════════════╣"); System.out.println("║ 1. Cadastrar livro ║"); System.out.println("║ 2. Buscar livro ║"); System.out.println("║ 3. Emprestar livro ║"); System.out.println("║ 4. Devolver livro ║"); System.out.println("║ 5. Listar acervo ║"); System.out.println("║ 0. Sair ║"); System.out.println("╚══════════════════════════════╝"); System.out.print("Escolha uma opção: "); } // ── CADASTRAR ──────────────────────────────────────────────────────────── static void cadastrar(String titulo, String autor, String isbn) { if (indiceIsbn.containsKey(isbn)) { System.out.println("ISBN já cadastrado: " + isbn); return; } Livro novo = new Livro(titulo, autor, isbn); acervo.add(novo); indiceIsbn.put(isbn, novo); } static void menuCadastrar() { System.out.print("Título : "); String titulo = sc.nextLine(); System.out.print("Autor : "); String autor = sc.nextLine(); System.out.print("ISBN : "); String isbn = sc.nextLine(); cadastrar(titulo, autor, isbn); System.out.println("✓ Livro cadastrado com sucesso!"); } // ── BUSCAR ─────────────────────────────────────────────────────────────── static void menuBuscar() { System.out.println("Buscar por: 1) Título 2) ISBN"); System.out.print("Opção: "); String op = sc.nextLine().trim(); if (op.equals("1")) { System.out.print("Digite parte do título: "); String trecho = sc.nextLine().toLowerCase(); boolean encontrou = false; // For-each percorre todo o acervo for (Livro livro : acervo) { if (livro.titulo.toLowerCase().contains(trecho)) { imprimirLivro(livro); encontrou = true; } } if (!encontrou) System.out.println("Nenhum livro encontrado."); } else { System.out.print("Digite o ISBN: "); String isbn = sc.nextLine().trim(); Livro livro = indiceIsbn.get(isbn); if (livro != null) imprimirLivro(livro); else System.out.println("ISBN não encontrado."); } } // ── EMPRESTAR ──────────────────────────────────────────────────────────── static void menuEmprestar() { System.out.print("ISBN do livro para emprestar: "); String isbn = sc.nextLine().trim(); Livro livro = indiceIsbn.get(isbn); if (livro == null) { System.out.println("Livro não encontrado."); } else if (!livro.disponivel) { System.out.println("Este livro já está emprestado."); } else { livro.disponivel = false; System.out.println("✓ \"" + livro.titulo + "\" emprestado com sucesso!"); } } // ── DEVOLVER ───────────────────────────────────────────────────────────── static void menuDevolver() { System.out.print("ISBN do livro para devolver: "); String isbn = sc.nextLine().trim(); Livro livro = indiceIsbn.get(isbn); if (livro == null) { System.out.println("Livro não encontrado."); } else if (livro.disponivel) { System.out.println("Este livro não estava emprestado."); } else { livro.disponivel = true; System.out.println("✓ \"" + livro.titulo + "\" devolvido. Disponível novamente!"); } } // ── LISTAR ACERVO ──────────────────────────────────────────────────────── static void listar() { System.out.println("\n── ACERVO COMPLETO (" + acervo.size() + " livros) ──"); int disponiveis = 0; for (Livro livro : acervo) { imprimirLivro(livro); if (livro.disponivel) disponiveis++; } System.out.println("\nDisponíveis : " + disponiveis); System.out.println("Emprestados : " + (acervo.size() - disponiveis)); } // ── AUXILIAR: imprime um livro formatado ───────────────────────────────── static void imprimirLivro(Livro livro) { String status = livro.disponivel ? "✓ Disponível" : "✗ Emprestado"; System.out.println("────────────────────────────────"); System.out.println("Título : " + livro.titulo); System.out.println("Autor : " + livro.autor); System.out.println("ISBN : " + livro.isbn); System.out.println("Status : " + status); } }
╔══════════════════════════════╗
║ SISTEMA DE BIBLIOTECA ║
╠══════════════════════════════╣
║ 1. Cadastrar livro ║
║ 2. Buscar livro ║
║ 3. Emprestar livro ║
║ 4. Devolver livro ║
║ 5. Listar acervo ║
║ 0. Sair ║
╚══════════════════════════════╝
Escolha uma opção: 3
ISBN do livro para emprestar: 978-0261102217
✓ "O Hobbit" emprestado com sucesso!
Escolha uma opção: 5
── ACERVO COMPLETO (5 livros) ──
────────────────────────────────
Título : O Hobbit
Autor : J.R.R. Tolkien
ISBN : 978-0261102217
Status : ✗ Emprestado
────────────────────────────────
Título : Dom Casmurro
Autor : Machado de Assis
ISBN : 978-8535910902
Status : ✓ Disponível
...
Disponíveis : 4
Emprestados : 1
Dica de extensão: Para ir além, tente adicionar uma funcionalidade de histórico de empréstimos usando outro ArrayList<String> que registra o título e a data de cada empréstimo com LocalDate.now().
Ao guardar cada livro também no HashMap com o ISBN como chave, a busca por ISBN é instantânea — não importa se o acervo tem 10 ou 10.000 livros. Sem o HashMap, seria necessário percorrer toda a lista a cada busca.
O menu usa do-while em vez de while porque precisamos exibir o menu pelo menos uma vez antes de verificar se o usuário quer sair. Com while comum, seria necessário ler a opção antes do loop — duplicando código.
Todos os métodos são static porque pertencem à classe e não a um objeto específico. Como o main também é estático, ele só consegue chamar diretamente outros métodos estáticos.
Ao converter o título do livro e o termo buscado para minúsculas antes de comparar, a busca funciona independente de como o usuário digita: "hobbit", "Hobbit" e "HOBBIT" encontram o mesmo livro.
✅ Separação de responsabilidades: Cada método faz exatamente uma coisa. cadastrar() cadastra, listar() lista, imprimirLivro() formata a saída. Isso é o primeiro passo para um código profissional e fácil de manter.
Teste sua compreensão do projeto Biblioteca:
Reforce o conteúdo desta aula com mais dois exercícios práticos: