En muchas ocasiones uno de los principales dolores de cabeza al trabajar con java es el manejo de excepciones nulas, debido a que esto puede botar un programa por completo, existen varias formas de manejar las null exceptions, depende mucho el tipo de dato que recibamos, sin embargo, hoy aprenderemos una de las mejores maneras de manejar los nulos utilizando la clase optional.
Declaración de la clase Optional
java.util.Optional<T> fue una clase introducida en java 8 como una mejora para el manejo de nulos dentro de java, y luego en java 11 le realizaron algunas mejoras que facilitaron el desarrollo del código, para usarla podemos ver el siguiente ejemplo de declaración:
// Caso 1: Cuando sabemos que habrá algún valor Optional<String> stringConValor = Optional.of("Hola Mundo!"); // Caso 2: Cuando no estamos seguros si el valor es nulo o no Optional<String> stringNoSeguro = Optional.ofNullable(null); // Caso 3: Cuando estamos seguros de que no existe ningún valor Optional<String> stringNulo = Optional.empty();
Caso 1:
Usualmente se usaría cuando sí necesitamos que se dispare una null exception, talvez por el propio flujo de la aplicación.
Caso 2:
Este probablemente será el más usado, debido a que no dispara null pointer exception y podemos enviarle o no un valor.
Caso 3:
El caso 3 nos permitirá usar Optional.empty() lo cuál devolverá una constante de tipo static final, esto es mejor que usar un = null por lo que dependiendo el flujo de nuestro sistema podremos verificar una constante nula.
Else condition:
Si quisiéramos hacer una validación else en la declaración de la variable o bien si el valor es un null, nos retornará siempre el valor default que le coloquemos, para ello podemos usar la función orElse():
String respuesta = Optional.ofNullable(traeData()).orElse("Hola Mundo!");
Nota: Java NO acepta null coalescing:
Ejemplo:
var respuesta = doSomething() ?: «Valor default»
Verificación del valor
Para verificar el estado del optional la clase nos brinda la función isPresent() la cuál nos devolverá un true o un false:
Optional<String> stringConValor = Optional.of("Hola Mundo!"); if (stringConValor.isPresent()) { System.out.println("Sí hay un valor"); } Optional<String> stringNoSeguro = Optional.ofNullable(null); if (stringNoSeguro.isPresent()) { System.out.println("Sí hay un valor"); }else{ System.out.println("No hay un valor"); } Optional<String> stringNulo = Optional.empty(); if (stringNulo.isPresent() == false) { System.out.println("El valor es nulo"); }
Para obtener el valor luego de verificar si es nulo podemos usar get():
Optional<String> stringConValor = Optional.ofNullable("Hola Mundo!"); if (stringConValor.isPresent()) { String texto = stringConValor.get(); }
Funciona de la misma manera para verificar instancias de clases:
Persona p = new Persona(); p = null; //Esto usualmente se declara en el constructor de la clase //Acá podemos hacer el procedimiento necesario con p para luego verificarlo con Optional Optional<Persona> persona = Optional.ofNullable(p); if (persona.isPresent()) { p = persona.get(); }else{ System.out.println("La instancia es nula"); }
Por último, recordemos que podemos usar patrones de diseño como singleton para asegurarnos de que no se declare una clase nula, sin embargo, esto dependerá mucho de como sea el flujo de nuestro sistema o el funcionamiento de la clase.