Menu
Coddy logo textTech

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.

challenge icon

Desafio

Fácil

Vamos 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) e durationMinutes (int). Adicione um método personalizado chamado getFormattedDuration() que retorne a duração em um formato amigável: [hours]h [minutes]m (por exemplo, 142 minutos se tornam 2h 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) e price (double). Adicione um construtor compacto que valide o preço; se o preço for menor ou igual a zero, lance uma IllegalArgumentException com a mensagem Price must be positive. Adicione também um método personalizado chamado printTicket() 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()
        
    }
}
quiz iconTeste seus conhecimentos

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

Pratique por conta própria: Compilador de Java online