[vc_row][vc_column][vc_column_text]Una de las características más interesantes que trajo Java 8 fue la clase Optional. El principal problema que esta clase intenta resolver es el famoso NullPointerException que muchos programadores conocen muy bien.
En esencia, esta es una clase contenedora que puede contener un valor opcional, que significa que puede contener un objeto o simplemente puede ser vacío.
Optional llega fuertemente relacionado a la programación funcional con Java y ayuda en este paradigma, pero también funciona fuera del mismo.
Empecemos con un simple caso de uso. Antes de Java 8, cualquier acceso a métodos o propiedades de un objeto podía resultar en un NullPointerException.
1 | String isocode = user.getAddress().getCountry().getIsocode().toUpperCase(); |
Si queremos estar seguros que no vamos a tener una excepción en este ejemplo, se requieren tener verificaciones para cada uno de los valores antes de acceder a ellos:
1 2 3 4 5 6 7 8 9 10 11 12 | if (user != null) { Address address = user.getAddress(); if (address != null) { Country country = address.getCountry(); if (country != null) { String isocode = country.getIsocode(); if (isocode != null) { isocode = isocode.toUpperCase(); } } } } |
Como puede observar esto se puede convertir en algo incomodo y difícil de mantener. Para simplificar este proceso, veremos como nos puede ayudar la clase Optional, para crear y verificar las instancias.
Creación de instancias de Optional
Considerar, un objeto de este tipo puede tener un valor o ser vacío. Se puede crear un Optional vacío utilizando un método con el mismo nombre:
1 2 3 4 5 | @Test(expected = NoSuchElementException.class) public void whenCreateEmptyOptional_thenNull(){ Optional<User> emptyOpt = Optional.empty(); emptyOpt.get(); } |
No debe ser sorpresa que al intentar acceder al valor de emptyOpt este resulta en NoSuchElementException.
Para crear un Optional que contenga un valor, se puede utilizar los métodos of() y ofNullable(). La diferencia entre ambos es que el método of() puede retornar un NullPointerException si pasa un valor null como argumento.
1 2 3 4 | @Test(expected = NullPointerException.class) public void whenCreateEmptyOptional_thenNullPointerException(){ Optional<User> opt = Optional.of(user); } |
Como puede ver, no podemos eliminar por completo al NullPointerException. Por esta razón, solo se debería utilizar of() cuando esta seguro que el objeto no sera null.
Si el objeto puede ser null y not-null, se debe utilizar el método ofNullabe():
1 | Optional<User> opt = Optional.ofNullable(user); |
[/vc_column_text][/vc_column][/vc_row][vc_row][vc_column][vc_column_text]
Accediendo al valor de los objetos Optional
Una forma de acceder dentro del objeto Optional es utilizando el método get():
1 2 3 4 5 6 | @Test public void whenCreateOfNullableOptional_thenOk() { String name = "John"; Optional<String> opt = Optional.ofNullable(name); assertEquals("John", opt.get()); } |
Sin embargo, tal como se vio anteriormente, este método lanza una excepción en caso de que el valor sea null. Para evitar esta excepción, puede elegir primero verificar si el valor esta presente o no:
1 2 3 4 5 6 7 8 | @Test public void whenCheckIfPresent_thenOk() { User user = new User("john@gmail.com", "1234"); Optional<User> opt = Optional.ofNullable(user); assertTrue(opt.isPresent()); assertEquals( user.getEmail, opt.get().getEmail()); } |
Otra opción para verificar que el valor se encuentra presente es el método ifPresent(). En forma adicional a la verificación, este método utiliza un Consumer y ejecuta la expresión lambda si el objeto no se encuentra vacío:
1 | opt.ifPresent( u -> assertEquals(user.getEmail(), u.getEmail()) ); |
En este ejemplo, la verificación sólo se realiza si el objeto es diferente de null.[/vc_column_text][/vc_column][/vc_row][vc_row][vc_column][vc_column_text]
Conclusión
El objeto Optional es una adición importante al lenguaje Java, que intenta minimizar el número de NullPointerException en el código, pero no es capaz de eliminar todos.
Es también una funcionalidad adicional bien diseñada y natural para la programación funcional agregada en Java 8.
Sobre todo, esta clase simple, pero poderosa ayuda a crear código, que es, simplemente más legible y menos propenso a errores que los procedimientos que se realizan en contraparte.
Puede revisar el artículo completo en Understanding, Accepting, and Leveraging Optional in Java y revisar información adicional en Java 8 Optional.[/vc_column_text][/vc_column][/vc_row]