Ir al contenido principal

Java Tip 24: conociendo la clase Optional

La documentación oficial nos dice:

Optional en Java es una clase de Java 8 que actúa como un contenedor para un valor que puede estar presente o no. Se utiliza para gestionar explícitamente los valores nulos y evitar NullPointerException, haciendo el código más claro y seguro. En lugar de retornar un valor null, que puede provocar errores, Optional permite crear objetos que pueden estar vacíos o contener un valor, lo que requiere que el programador maneje explícitamente el caso de que no haya valor.

Con la clase Optional podemos:

  • Evitar el riesgo de un NullPointerException.
  • Checar si un valor existe o no. 
  • Recuperar un valor está presente o no. 
  • Ejecutar acciones en función si el valor esta presente o no.

Esta clase promueve un estilo de programación más seguro y expresivo.

Importamos esta clase:

import java.util.Optional;

Una vez importada la podremos usar. Veamos la clase:

public final class Optional<T>{}

Como se puede ver se trata de una clase genérica, lo cual nos permite que el objeto que contenga (o no) sea de cualquier clase.

Existen varias formas para crear una variable tipo Optional :

1. Forma vacía:

Optional<String> optionalStrEmpty = Optional.empty();

Optional<Boolean> optionalBoolEmpty = Optional.empty();

Optional<Empleado> optionalEmpleadoEmpty = Optional.empty();

Uso:

optionalStrEmpty.ifPresent(str -> System.out.println("Hola, "+str));

optionalBoolEmpty.ifPresent(b -> {
  if(b){
       Systemout.print("\nHola");
  }
});


if(optionalEmpleadoEmpty.isPresent()) {
    System.out.println("El empleado existe");
 }

2. Con valor distinto a nulo:

Optional<String> nonEmptyOptional = Optional.of("Hello");
Optional<Boolean> nonEmptyBoolOptional = Optional.of(true);
Optional<Boolean> nonEmptyEmpOptional = Optional.of(new Empleado());

Uso:

String valorStr = nonEmptyOptional.get();
Boolean valorBool = nonEmptyBoolOptional.get();
Empleado valorEmp = nonEmptyEmpOptional.get();

3. Con un valor nulo:

Optional<String> nullableOptional = Optional.ofNullable(null);

Uso:

public Optional<String> buscarUsuario(String id) {
    if ("123".equals(id)) {
        return Optional.of("Usuario encontrado");
    }
    return Optional.empty();
}


// Uso
Optional<String> obtEmp = this.buscarUsuario(nullableOptional); 

En pocas palabras:

  • Optional.of(value) → crea un Optional con un valor no nulo. 
  • Optional.ofNullable(value) → crea un Optional que puede ser nulo. 
  • Optional.empty() → crea un Optional vacío.

Métodos principales de la clase genérica Optional

Algunos de los métodos principales son:

  • isPresent() → devuelve true si hay valor. 
  • ifPresent(Consumer) → ejecuta una acción si hay valor. 
  • get() → obtiene el valor (lanza excepción si está vacío). 
  • orElse(defaultValue) → devuelve el valor o un valor por defecto. 
  • orElseGet(Supplier) → similar a orElse, pero recibe un proveedor. 
  • orElseThrow() → lanza excepción si está vacío.

Aquí una tabla que muestra un resumen de los métodos principales de la clase Optional :

Método Propósito Retorno Uso común Nota clave
Optional.of(value) Crear un Optional con valor no nulo Optional<T> Cuando sabes que el valor existe Lanza NullPointerException si value es null
Optional.ofNullable(value) Crear un Optional que acepta nulos Optional<T> En entradas/retornos que pueden ser null Si value es null, devuelve Optional.empty()
Optional.empty() Representar ausencia explícita de valor Optional<T> Retornos de métodos cuando no hay resultado Útil para evitar null
isPresent() Verificar si hay valor boolean Checks rápidos (no recomendado en estilo funcional) Prefiere ifPresent / orElse
isEmpty() Verificar si está vacío boolean Java 11+ para legibilidad inversa Equivalente a !isPresent()
ifPresent(Consumer) Ejecutar acción si hay valor void Side effects controlados No opera si está vacío
ifPresentOrElse(Consumer, Runnable) Acciones para presente/ausente void Java 9+, flujo claro Útil para bifurcar lógica
get() Obtener el valor T Evita su uso; puede lanzar excepción Lanza NoSuchElementException si está vacío
orElse(default) Valor o por defecto T Por defecto barato/constante Evalúa default siempre (aunque haya valor)
orElseGet(Supplier) Valor o proveedor diferido T Por defecto costoso (lazy) Ejecuta Supplier solo si está vacío
orElseThrow() Lanzar excepción si vacío T Forzar presencia Lanza NoSuchElementException por defecto
orElseThrow(Supplier) Lanzar excepción personalizada T Mensajes/Tipos de excepción claros Proveedor ejecuta solo si está vacío
map(Function) Transformar valor presente Optional<U> Encadenar transformaciones No ejecuta si está vacío
flatMap(Function) Transformar y aplanar Optional<Optional<U>> Optional<U> Evitar anidación de Optional La función debe devolver Optional
filter(Predicate) Mantener valor si cumple condición Optional<T> Validaciones inline Devuelve empty si no cumple

Recomendaciones:

  • Usar Optional como tipo de retorno, no como parámetro ni atributo de clase. 
  • Evitar abusar de get(), preferir orElse, orElseGet o ifPresent. 
  • Ideal para flujos con Streams y operaciones funcionales

Enlaces:

https://adictosaltrabajo.com/2015/03/02/optional-java-8/
https://medium.com/@pratik.941/mastering-optional-in-java-8-a-comprehensive-guide-3131eac600dc




Comentarios

Entradas populares de este blog

Java Tip 28: hilos virtuales en Java

Con Java 21 entra un nuevo concepto: hilos virtuales java ( Java Virtual Threads ).  La cual es una nueva característica que nos permite crear miles o millones de hilos (tareas en paralelo). Los cuales se diferencian de los hilos comunes ( Platform Threads ) al no depender del sistema operativo , puesto que son virtuales. De estos se encargará la JVM. Al usar hilos virtuales ahorramos recursos del procesador y de memoria del sistema , sin importar si estamos creando y/o usando miles o millones. Los hilos virtuales son ideales para aplicaciones modernas donde se requiere esperar y recibir respuestas o acceder a bases de datos remotas, entre otras cosas. Además no impide usar los hilos comunes que dependen del sistema operativo. Observemos un ejemplo de uso de hilos virtuales. VirtualThreadsDemo.java package com.comunidad.demo; public class VirtualThreadsDemo { public static void main (String [] args) throws InterruptedException { // Crear un Virtual Th...

Java Tip 30: Date & Time API

Quien lleva tiempo programando en Java sabrá que el formateo de fechas es un verdadero dolor de cabeza. Afortunadamente desde la versión 8 Java posee una nuevo Date y Time API que permite ahorrarnos algunos bloques de código engorrosos y tediosos. ¿Qué veremos? Nos enfocaremos en estas clases del paquete `` java.time ``: Instant: para un punto en el tiempo, un instante (antes se usaba System.currentTimeMillis() ). LocalDate: para obtener la fecha del sistema. LocalTime: para obtener la hora del sistema LocalDateTime: para obtener fecha y hora del sistema. ZonedDateTime: para obtener fecha y hora del sistema por zona horaria. TestTimeAPI.java import java.time.LocalTime ; import java.time.LocalDate ; import java.time.LocalDateTime ; public class TestTimeAPI { public static void main (String [] args){ System. out . println ( "\t Nueva API Time de Java." ); LocalTime horaActual = LocalTime. now (); L...

Java Tip 1: Importaciones por default

Tip 1 : Todas las clases del paquete java.lang se importan por defecto. Podríamos hacer algo como esto: import java.lang.System ; import java.lang.String ; import java.lang.Boolean ; import java.lang.Integer ; import java.lang.Short ; import java.lang.StringBuilder ; import java.lang.StringBuffer ; O cosas (aberrantes) como: //Traernos todas las clases del paquete java.lang import java.lang.* ; Sin embargo, no es necesario. Repitamos esto como un mantra: Todas las clases del paquete  java.lang  se importan por defecto, no es necesario escribir de más .