Java 17, 18, 19, 20 y 21 han traído un ritmo de innovación sin precedentes. Características que antes requerían librerías externas o docenas de líneas de código ahora son parte del lenguaje. Esta última parte del curso resume las novedades más impactantes para el código del día a día.
Records (Java 16 — estable)
Ya vistos en el capítulo de Genéricos, los records son la solución definitiva al problema de las clases de datos en Java:
// Un record con validación en el compact constructor
public record Temperatura(double valor, String unidad) {
public Temperatura {
if (!"C".equals(unidad) && !"F".equals(unidad) && !"K".equals(unidad)) {
throw new IllegalArgumentException("Unidad inválida: " + unidad);
}
if ("K".equals(unidad) && valor < 0) {
throw new IllegalArgumentException("Kelvin no puede ser negativo");
}
}
public Temperatura aCelsius() {
return switch (unidad) {
case "F" -> new Temperatura((valor - 32) * 5 / 9, "C");
case "K" -> new Temperatura(valor - 273.15, "C");
default -> this;
};
}
}
Sealed classes (Java 17 — estable)
Las clases selladas (sealed) controlan qué clases pueden extenderlas. Son perfectas para modelar jerarquías cerradas y se combinan muy bien con el pattern matching en switch:
public sealed interface Forma
permits Circulo, Rectangulo, Triangulo {}
public record Circulo(double radio) implements Forma {}
public record Rectangulo(double ancho, double alto) implements Forma {}
public record Triangulo(double base, double altura) implements Forma {}
// El compilador verifica que el switch es exhaustivo
double calcularArea(Forma f) {
return switch (f) {
case Circulo c -> Math.PI * c.radio() * c.radio();
case Rectangulo r -> r.ancho() * r.alto();
case Triangulo t -> t.base() * t.altura() / 2;
};
}
Pattern Matching en switch (Java 21 — estable)
El pattern matching en switch combina el tipo check, el cast y la extracción de datos en una sola expresión elegante:
Object objeto = obtenerAlgo();
String descripcion = switch (objeto) {
case Integer i when i > 0 -> "Entero positivo: " + i;
case Integer i -> "Entero no positivo: " + i;
case String s -> "Cadena de " + s.length() + " chars";
case List> l -> "Lista con " + l.size() + " elementos";
case null -> "Valor nulo";
default -> "Otro tipo: " + objeto.getClass().getSimpleName();
};
Text Blocks (Java 15 — estable)
// SQL multilínea legible
String consulta = """
SELECT u.nombre, u.email, p.titulo
FROM usuarios u
JOIN pedidos p ON p.id_usuario = u.id
WHERE u.activo = true
AND p.fecha >= '2025-01-01'
ORDER BY u.nombre
""";
// HTML con interpolación de variables
String nombre = "Java 21";
String pagina = """
%s
Bienvenido a %s
""".formatted(nombre, nombre);
SequencedCollection (Java 21)
Java 21 añadió la interfaz SequencedCollection a la jerarquía de colecciones, que garantiza un orden definido y da acceso al primer y último elemento:
SequencedCollectionlista = new ArrayList<>(List.of("a", "b", "c")); System.out.println(lista.getFirst()); // a System.out.println(lista.getLast()); // c lista.addFirst("inicio"); lista.addLast("fin"); SequencedCollection invertida = lista.reversed();
Resumen del camino hacia Java 21
Versión | Novedades destacadas |
Java 8 (2014) | Lambdas, Streams, Optional, default methods |
Java 11 (2018) | var en lambdas, HTTP Client, String methods nuevos |
Java 14 (2020) | Switch expressions, Records (preview) |
Java 16 (2021) | Records estables, Pattern matching instanceof |
Java 17 (2021) | Sealed classes, nuevos text blocks estables (LTS) |
Java 21 (2023) | Virtual Threads, Pattern matching en switch, SequencedCollections (LTS) |
Para mantenerse al día con las novedades de Java, la mejor fuente es JEP (Java Enhancement Proposal) en openjdk.org/jeps. Cada versión de Java desde Java 9 sigue un ciclo de 6 meses, con versiones LTS cada 2 años.
Imagen: Pexels / Daniil Komov
