Optional y Records (Java 14+)
NullPointerException es el error más común en Java: ocurre cuando intentas usar un método o atributo de una variable que es null. Optional<T> es la solución moderna: en lugar de retornar null cuando algo no se encuentra, retornas Optional.empty(). El código que recibe el Optional es forzado a manejar el caso "no hay valor" antes de acceder al contenido. Es como una caja transparente: puedes ver si hay algo adentro antes de intentar sacarlo.
Los Records (introducidos en Java 16) son clases de datos inmutables con sintaxis ultra-concisa. En lugar de escribir 30 líneas con constructor, getters, equals, hashCode y toString, escribes una sola línea: record Persona(String nombre, int edad) {}. Java genera todo lo demás automáticamente. Los accessors se llaman igual que el campo (p.nombre() en lugar de p.getNombre()).
Son perfectos para DTOs (Data Transfer Objects), respuestas de API, y cualquier dato que no deba modificarse después de crearse.
import java.util.Optional;
// Optional - evitar null
public Optional<String> buscarEmail(String nombre) {
Map<String, String> emails = Map.of(
"Ana", "ana@mail.com",
"Bob", "bob@mail.com"
);
return Optional.ofNullable(emails.get(nombre));
}
// Uso de Optional
Optional<String> email = buscarEmail("Ana");
// Verificar si tiene valor
if (email.isPresent()) {
System.out.println(email.get());
}
// ifPresent - callback si hay valor
email.ifPresent(e -> System.out.println("Email: " + e));
// orElse - valor por defecto
String resultado = email.orElse("sin-email@default.com");
// orElseGet - valor por defecto con función
String resultado2 = email.orElseGet(() -> generarEmail("Ana"));
// orElseThrow - lanzar excepción si vacío
String emailSeguro = email.orElseThrow(() ->
new RuntimeException("Usuario sin email"));
// map - transformar el valor si existe
Optional<Integer> longitud = email.map(String::length);
// filter - filtrar el valor
Optional<String> emailValido = email
.filter(e -> e.contains("@"));
// Records (Java 16) - clases de datos inmutables
record Punto(double x, double y) {}
record Persona(String nombre, int edad) {
// Constructor compacto con validación
Persona {
if (nombre.isBlank()) throw new IllegalArgumentException("Nombre requerido");
if (edad < 0) throw new IllegalArgumentException("Edad inválida");
}
// Método de instancia
public String presentar() {
return nombre + " (" + edad + " años)";
}
}
var p = new Persona("Ana", 25);
System.out.println(p.nombre()); // Ana (accessor, no getNombre)
System.out.println(p); // Persona[nombre=Ana, edad=25]
Practica esta lección
Resuelve los ejercicios del curso de Java en la app, gratis y con corrección automática.
Empezar a practicar