Menu
Coddy logo textTech

Records (Java 16+)

Parte de la sección Programación Orientada a Objetos del Journey de Java de Coddy — lección 51 de 87.

Al crear clases sencillas que transportan datos, a menudo se escribe código repetitivo (boilerplate): campos privados, un constructor, getters, toString(), equals(), y hashCode(). Java 16 introdujo los records para eliminar este tedio.

Un record es una clase especial diseñada para almacenar datos inmutables. Se declara con la palabra clave record seguida de la lista de componentes:

record Person(String name, int age) { }

// Esa única línea proporciona automáticamente:
// - campos private final: name y age
// - un constructor: Person(String name, int age)
// - métodos de acceso: name() y age()
// - toString(), equals(), y hashCode()

Usar un record es sencillo:

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]

Observa que los métodos de acceso no utilizan el prefijo get; simplemente se nombran igual que los campos. Los records son implícitamente final, por lo que no pueden ser extendidos. Todos los campos son también final, lo que hace que los records sean inherentemente inmutables.

Puedes añadir métodos personalizados y sobrescribir los generados automáticamente si es necesario. También puedes añadir validación en un constructor compacto:

record Person(String name, int age) {
    public Person {
        if (age < 0) throw new IllegalArgumentException("Age cannot be negative");
    }
}

Los records son perfectos para DTOs, respuestas de API o cualquier escenario en el que necesites un contenedor de datos simple e inmutable sin escribir código repetitivo.

challenge icon

Desafío

Fácil

Vamos a construir un sistema de reserva de boletos de cine que muestre la elegancia de los records de Java. Verás cómo los records eliminan el código repetitivo (boilerplate) mientras te permiten agregar métodos personalizados y validación.

Organizarás tu código en tres archivos:

  • Movie.java: Crea un record que represente una película con tres componentes: title (String), genre (String) y durationMinutes (int). Agrega un método personalizado llamado getFormattedDuration() que devuelva la duración en un formato amigable: [hours]h [minutes]m (por ejemplo, 142 minutos se convierte en 2h 22m). Usa la división entera y el módulo para calcular las horas y los minutos restantes.
  • Ticket.java: Crea un record que represente un boleto de cine con tres componentes: movie (Movie), seatNumber (String) y price (double). Agrega un constructor compacto que valide el precio; si el precio es menor o igual a cero, lanza una IllegalArgumentException con el mensaje "Price must be positive". También agrega un método personalizado llamado printTicket() que devuelva una cadena multilínea:
    ========== TICKET ==========
    Movie: [movie title]
    Genre: [movie genre]
    Duration: [formatted duration from movie]
    Seat: [seatNumber]
    Price: $[price]
    ============================
  • Main.java: ¡Une tu sistema de reservas! Recibirás cinco entradas: título de la película (String), género (String), duración en minutos (int), número de asiento (String) y precio del boleto (double).

    Crea un record Movie con las tres primeras entradas, luego crea un record Ticket con la película, el número de asiento y el precio. Imprime el resultado de llamar a printTicket() en tu boleto.

Recibirás cinco entradas en orden: título de la película, género, duración (minutos), número de asiento y precio.

Observa qué tan limpios son los records en comparación con las clases tradicionales: no es necesario escribir constructores, getters, toString(), equals() o hashCode(). El constructor compacto te permite agregar validación sin repetir las asignaciones de campos, ¡y aún puedes agregar métodos personalizados cuando sea necesario!

Hoja de referencia

Java 16 introdujo los records para eliminar el código repetitivo en las clases simples que transportan datos. Un record es una clase especial diseñada para contener datos inmutables.

Declara un record con la palabra clave record seguida de la lista de componentes:

record Person(String name, int age) { }

Esto proporciona automáticamente:

  • Campos privados y finales
  • Un constructor
  • Métodos de acceso (sin el prefijo get)
  • toString(), equals() y hashCode()

Uso de un record:

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]

Los records son implícitamente final y no se pueden extender. Todos los campos son final, lo que hace que los records sean intrínsecamente inmutables.

Añade validación usando un constructor compacto:

record Person(String name, int age) {
    public Person {
        if (age < 0) throw new IllegalArgumentException("Age cannot be negative");
    }
}

Puedes añadir métodos personalizados a los records:

record Person(String name, int age) {
    public String getInfo() {
        return name + " is " + age + " years old";
    }
}

Pruébalo tú mismo

import java.util.Scanner;

class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        
        // Leer 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: Crear un record Movie con title, genre, y durationMinutes
        
        // TODO: Crear un record Ticket con movie, seatNumber, y price
        
        // TODO: Imprimir el ticket usando el método printTicket()
        
    }
}
quiz iconPonte a prueba

Esta lección incluye un breve cuestionario. Empieza la lección para responderlo y registrar tu progreso.

Todas las lecciones de Programación Orientada a Objetos