Records (Java 16+)
Parte da seção Programação Orientada a Objetos do Journey de Java da Coddy. Lição 51 de 87.
Ao criar classes simples que carregam dados, você frequentemente escreve código boilerplate repetitivo: campos privados, um construtor, getters, toString(), equals() e hashCode(). O Java 16 introduziu os records para eliminar esse trabalho tedioso.
Um record é uma classe especial projetada para armazenar dados imutáveis. Você o declara com a palavra-chave record seguida pela lista de componentes:
record Person(String name, int age) { }
// Essa única linha fornece automaticamente:
// - campos private final: name e age
// - um construtor: Person(String name, int age)
// - métodos acessores: name() e age()
// - toString(), equals() e hashCode()Usar um record é simples:
Person p = new Person("Alice", 30);
System.out.println(p.name()); // Alice
System.out.println(p.age()); // 30
System.out.println(p); // Person[name=Alice, age=30]Observe que os métodos acessores não usam o prefixo get: eles recebem simplesmente o nome dos campos. Os records são implicitamente final, portanto não podem ser estendidos. Todos os campos também são final, o que torna os records inerentemente imutáveis.
Você pode adicionar métodos personalizados e substituir os métodos gerados automaticamente, se necessário. Você também pode adicionar validação em um construtor compacto:
record Person(String name, int age) {
public Person {
if (age < 0) throw new IllegalArgumentException("Age cannot be negative");
}
}Records são perfeitos para DTOs, respostas de API ou qualquer cenário em que você precise de um contêiner de dados simples e imutável sem escrever código boilerplate.
Desafio
FácilVamos criar um sistema de reserva de ingressos de cinema que demonstra a elegância dos records do Java. Você verá como os records eliminam código boilerplate, permitindo ainda adicionar métodos personalizados e validação.
Você organizará seu código em três arquivos:
Movie.java: Crie um record que represente um filme com três componentes:title(String),genre(String) edurationMinutes(int). Adicione um método personalizado chamadogetFormattedDuration()que retorne a duração em um formato amigável:[hours]h [minutes]m(por exemplo, 142 minutos se tornam2h 22m). Use divisão inteira e módulo para calcular as horas e os minutos restantes.Ticket.java: Crie um record que represente um ingresso de cinema com três componentes:movie(Movie),seatNumber(String) eprice(double). Adicione um construtor compacto que valide o preço; se o preço for menor ou igual a zero, lance umaIllegalArgumentExceptioncom a mensagemPrice must be positive. Adicione também um método personalizado chamadoprintTicket()que retorne uma string multilinha:========== TICKET ========== Movie: [movie title] Genre: [movie genre] Duration: [formatted duration from movie] Seat: [seatNumber] Price: $[price] ============================Main.java: Reúna seu sistema de reservas! Você receberá cinco entradas: título do filme (String), gênero (String), duração em minutos (int), número do assento (String) e preço do ingresso (double).Crie um record Movie com as três primeiras entradas e, em seguida, crie um record Ticket com o filme, o número do assento e o preço. Imprima o resultado da chamada de
printTicket()no seu ingresso.
Você receberá cinco entradas na seguinte ordem: título do filme, gênero, duração (minutos), número do assento e preço.
Observe como os records são mais limpos em comparação com as classes tradicionais: não é necessário escrever construtores, getters, toString(), equals() ou hashCode(). O construtor compacto permite adicionar validação sem repetir atribuições de campos, e você ainda pode adicionar métodos personalizados quando necessário!
Experimente você mesmo
import java.util.Scanner;
class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
// Ler entradas
String title = scanner.nextLine();
String genre = scanner.nextLine();
int durationMinutes = Integer.parseInt(scanner.nextLine());
String seatNumber = scanner.nextLine();
double price = Double.parseDouble(scanner.nextLine());
// TODO: Crie um record Movie com title, genre e durationMinutes
// TODO: Crie um record Ticket com o movie, seatNumber e price
// TODO: Imprima o ticket usando o método printTicket()
}
}
Esta lição inclui um quiz rápido. Comece a lição para respondê-lo e acompanhar seu progresso.
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 Personalizada2Modificadores 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 IteratorPratique por conta própria: Compilador de Java online