Introducción a los records
Declare records como contenedores concisos e inmutables de datos y comprenda sus miembros generados automáticamente.
Introducción a los records es una lección gratuita de Java Academy en CoddyKit. Esta es la lección 1 de 4. Puedes leer la lección completa abajo gratuitamente — luego la practicas en el navegador con un editor de código integrado y un tutor de IA 24/7. Forma parte de la ruta de aprendizaje de Java Academy, y tu progreso se sincroniza en la web y la app de CoddyKit. El curso de Java Academy incluye 4 lecciones en total.
Introducción a los records
Los Records de Java (Java 16+) son una forma concisa de declarar clases inmutables portadoras de datos. Generan automáticamente el código repetitivo: constructor, getters, equals, hashCode y toString.
Declarar un record
Use la palabra clave record seguida del nombre del record y de una lista de componentes. Cada componente se convierte en un campo private final y en un método accesor público.
record Point(double x, double y) {}
Point p = new Point(3.0, 4.0);
System.out.println(p.x()); // 3.0 (accessor, not getX())
System.out.println(p.y()); // 4.0
System.out.println(p); // Point[x=3.0, y=4.0]
System.out.println(p.equals(new Point(3.0, 4.0))); // trueMiembros generados automáticamente
El compilador genera automáticamente para cada record: el constructor canónico, los accessors públicos, equals(), hashCode() y toString(). No es necesario escribirlos manualmente.
record Product(String name, double price, int stock) {}
Product p1 = new Product("Widget", 9.99, 100);
Product p2 = new Product("Widget", 9.99, 100);
System.out.println(p1.name()); // Widget
System.out.println(p1.price()); // 9.99
System.out.println(p1.equals(p2)); // true (structural)
System.out.println(p1.hashCode() == p2.hashCode()); // true
System.out.println(p1); // Product[name=Widget, price=9.99, stock=100]Los records son inmutables
Los componentes de un record son final. No puede modificarlos después de la construcción; los records representan objetos de valor inmutables.
record Money(long cents, String currency) {}
Money price = new Money(999, "USD");
// price.cents = 500; // Compile error — final field!
// To "update" a record, create a new one
Money discounted = new Money(price.cents() - 100, price.currency());
System.out.println(discounted); // Money[cents=899, currency=USD]Los records solo extienden Object
Los records extienden implícitamente java.lang.Record y no pueden extender otras clases. Sí pueden implementar interfaces.
interface Describable { String describe(); }
record Circle(double radius) implements Describable {
public String describe() {
return String.format("Circle with radius %.1f", radius);
}
public double area() {
return Math.PI * radius * radius;
}
}
Circle c = new Circle(5.0);
System.out.println(c.describe()); // Circle with radius 5.0
System.out.printf("Area: %.2f%n", c.area()); // Area: 78.54Records en colecciones
Como los records implementan correctamente equals y hashCode basándose en todos sus componentes, funcionan correctamente como claves de Map y elementos de Set.
import java.util.*;
record Coordinate(int row, int col) {}
Map<Coordinate, String> grid = new HashMap<>();
grid.put(new Coordinate(0, 0), "Origin");
grid.put(new Coordinate(1, 2), "Target");
// Lookup with equal-valued record works correctly
System.out.println(grid.get(new Coordinate(0, 0))); // Origin
System.out.println(grid.get(new Coordinate(1, 2))); // Target
Set<Coordinate> visited = new HashSet<>();
visited.add(new Coordinate(3, 3));
System.out.println(visited.contains(new Coordinate(3, 3))); // trueRecords como DTO
Los records son ideales para los Data Transfer Objects (DTO) de las API REST: transportan datos entre capas sin comportamiento.
record CreateUserRequest(String email, String displayName, String plan) {}
record UserResponse(long id, String email, String displayName,
String plan, String createdAt) {}
// Simulating a service call
static UserResponse createUser(CreateUserRequest req) {
long id = 42L;
return new UserResponse(id, req.email(), req.displayName(),
req.plan(), java.time.Instant.now().toString());
}
CreateUserRequest req = new CreateUserRequest("alice@example.com", "Alice", "PRO");
UserResponse resp = createUser(req);
System.out.println(resp);Desestructurar records
Los records combinan bien con el pattern matching. Puede desestructurarlos en expresiones switch (Java 21+).
sealed interface Shape permits Circle, Rectangle, Triangle {}
record Circle(double radius) implements Shape {}
record Rectangle(double width, double height) implements Shape {}
record Triangle(double base, double height) implements Shape {}
static double area(Shape s) {
return switch (s) {
case Circle(double r) -> Math.PI * r * r;
case Rectangle(double w, double h) -> w * h;
case Triangle(double b, double h) -> 0.5 * b * h;
};
}
System.out.printf("%.2f%n", area(new Circle(5))); // 78.54
System.out.printf("%.2f%n", area(new Rectangle(4, 6))); // 24.00Serialización de records
Los records implementan Serializable de forma natural cuando se declaran para ello. Funcionan correctamente con bibliotecas JSON (Jackson, Gson) sin configuración adicional.
// With Jackson (add @JsonProperty if needed)
import com.fasterxml.jackson.databind.ObjectMapper;
record OrderSummary(String orderId, double total, String status) {}
ObjectMapper mapper = new ObjectMapper();
OrderSummary order = new OrderSummary("ORD-001", 149.99, "SHIPPED");
String json = mapper.writeValueAsString(order);
System.out.println(json);
// {"orderId":"ORD-001","total":149.99,"status":"SHIPPED"}
OrderSummary restored = mapper.readValue(json, OrderSummary.class);
System.out.println(order.equals(restored)); // trueRecords anidados
Los records pueden contener otros records como componentes, lo que permite construir grafos de objetos inmutables y completos.
record Address(String street, String city, String country) {}
record Customer(long id, String name, Address address) {}
Address addr = new Address("123 Main St", "New York", "US");
Customer customer = new Customer(1L, "Alice", addr);
System.out.println(customer.name()); // Alice
System.out.println(customer.address().city()); // New York
System.out.println(customer); // Customer[id=1, name=Alice, address=Address[street=123 Main St, city=New York, country=US]]Limitaciones de los records
Los records tienen algunas restricciones que debe conocer:
- No pueden extender otras clases (extienden Record implícitamente)
- Los componentes siempre son final; no puede haber estado mutable
- No puede declarar campos de instancia fuera de la lista de componentes
- No pueden ser abstractos
// Records CAN have static fields and methods
record Temperature(double celsius) {
static final double ABSOLUTE_ZERO = -273.15;
public double toFahrenheit() {
return celsius * 9.0/5.0 + 32;
}
public static Temperature fromFahrenheit(double f) {
return new Temperature((f - 32) * 5.0/9.0);
}
}
System.out.println(Temperature.fromFahrenheit(98.6)); // Temperature[celsius=37.0]Comprobación rápida
¿Qué miembros genera automáticamente el compilador de Java para un record?
Repaso: introducción a los records
Conclusiones principales:
- Los records declaran estructuras inmutables portadoras de datos con un mínimo de código repetitivo
- Se generan automáticamente: el constructor canónico, los accessors, equals, hashCode y toString
- Los componentes son final; los records son inmutables por diseño
- Los records pueden implementar interfaces, pero no pueden extender clases
- Son perfectos para DTO, objetos de valor y respuestas de API
- Funcionan correctamente como claves de HashMap y elementos de HashSet gracias a la igualdad estructural
Preguntas frecuentes
¿La lección «Introducción a los records» es gratis?
Sí — el texto completo de «Introducción a los records» es gratis para leer aquí en la web. Para practicarla de forma interactiva (editor de código integrado y tutor de IA 24/7) y desbloquear el resto del curso de Java Academy, actualiza a CoddyKit PRO. El curso de Java Academy incluye 4 lecciones en total.
¿Qué aprenderé en «Introducción a los records»?
Declare records como contenedores concisos e inmutables de datos y comprenda sus miembros generados automáticamente. Practicas Java Academy con código real que ejecutas directamente en el navegador, y un tutor de IA 24/7 responde tus preguntas mientras trabajas en la lección.
¿Necesito experiencia previa para empezar Java Academy?
No se requiere experiencia previa. Java Academy en CoddyKit está estructurado para principiantes hasta estudiantes avanzados, así que puedes empezar aquí o desde el inicio y avanzar a tu ritmo. Esta es la lección 1 de 4.
¿Cuánto tiempo toma la lección «Introducción a los records»?
La mayoría de las lecciones de CoddyKit toman alrededor de 5–10 minutos. Cada una es compacta e interactiva, así que avanzas constantemente y retomas exactamente por donde dejaste en la web y la app.
¿Puedo escribir y ejecutar código en esta lección de Java Academy?
Sí. Cada lección de Java Academy incluye un editor de código integrado, así que escribes y ejecutas código real directamente en tu navegador y obtienes retroalimentación instantánea de IA — sin configuración local necesaria.
Todas las lecciones de este curso
- Introducción a los records
- Constructores compactos y validación
- Métodos personalizados en records
- Records frente a clases y Lombok