Java 8 Optional class to alleviate some of the pains of unsightly null pointer checks and defensive coding
The most prevalent runtime exception (aka unchecked) exception in Java is the NullPointerException. You need to code defensively to avoid NullPointerException as shown below. Later, we will see how the class java.util.Optional that was introduced in Java 8 will alleviate this problem to some extent.
Pre Java 8 without the java.util.Optional class
public class Person { private String name; private int age; private HealthInsurance insurance; //getters and setter }
public class HealthInsurance { private String name; private Extra[] extras; //getters and setters }
public class Extra { private String name; //getters and setters }
Now, here is the main class that invokes printExtras(Person person), where you need to check for null
public class PersonTest { public static void main(String[] args) { Person person1 = new Person(); person1.setName("John"); printExtras(person1); Person person2 = new Person(); person2.setName("Peter"); HealthInsurance healthIns = new HealthInsurance(); Extra[] healthExtras = { new Extra("Physio"), new Extra("Optical"), new Extra("Chiro") }; healthIns.setExtras(healthExtras); person2.setInsurance(healthIns); printExtras(person2); } private static void printExtras(Person person) { if (person != null && person.getInsurance() != null && person.getInsurance().getExtras() != null) { Extra[] extras = person.getInsurance().getExtras(); for (Extra extra : extras) { System.out.println(extra.getName()); } } } }
In Java 8 with java.util.Optional class
Take note of the Optional class.
package com.java8.examples; import java.util.Optional; public class Person { private String name; private int age; private Optional<HealthInsurance> insurance = Optional.empty(); //default public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public Optional<HealthInsurance> getInsurance() { return insurance; } public void setInsurance(Optional<HealthInsurance> insurance) { this.insurance = insurance; } }
package com.java8.examples; import java.util.Optional; public class HealthInsurance{ private String name; private Optional<Extra[]> extras = Optional.empty(); //default public String getName() { return name; } public void setName(String name) { this.name = name; } public Optional<Extra[]> getExtras() { return extras; } public void setExtras(Optional<Extra[]> extras) { this.extras = extras; } }
package com.java8.examples; public class Extra { private String name; public Extra(String name) { super(); this.name = name; } public String getName() { return name; } }
Finally, the main class that make use of the Optional.of methods, and the printExtras(Optional
package com.java8.examples; import java.util.Arrays; import java.util.Collections; import java.util.List; import java.util.Optional; import java.util.function.Consumer; public class PersonTest { public static void main(String[] args) { Person person1 = new Person(); person1.setName("John"); Optional<Person> p1 = Optional.of(person1); printExtras(p1); Person person2 = new Person(); person2.setName("Peter"); // health ins and extras are supplied HealthInsurance healthIns = new HealthInsurance(); Extra[] healthExtras = { new Extra("Physio"), new Extra("Optical"), new Extra("Chiro") }; healthIns.setExtras(Optional.of(healthExtras)); person2.setInsurance(Optional.of(healthIns)); Optional<Person> p2 = Optional.of(person2); printExtras(p2); } private static void printExtras(Optional<Person> person) { person .flatMap(Person::getInsurance) .flatMap(HealthInsurance::getExtras) .ifPresent((p) -> {for(int i = 0; i < p.length; i++) { System.out.println(p[i].getName()); } }); } }
Both approaches outputs
Physio
Optical
Chiro
Here are the convenient methods that the Optional class support
- ifPresent( ): returns true if a value is present in the optional.
- get( ): returns a reference to the item contained in the optional object, if present, otherwise throws a NoSuchElementException.
- ifPresent(Consumer<T>consumer): passes the optional value, if present, to the provided Consumer (lambda expression or method reference).
- orElse(T other): returns the value, if present, otherwise returns the value in other.
- orElseGet(Supplier<T> other): returns the value if present, otherwise returns the value provided by the Supplier (lambda expression or method reference).
- orElseThrow(Supplier<T> exceptionSupplier): returns the value if present, otherwise throws the exception provided by the Supplier (lambda expression or method reference)
Note: In Java you cannot simply get rid of the null references that have historically existed, but before Java 8, you need to rely on your code and proper documentation to understand if a reference is optional. java.util.Optional<T> class has been added to deal with optional object references. The intention with the Optional class is not to replace every null-able reference, but to help in the creation of more robust APIs you could tell if you can expect an optional reference by reading the signature of a method.
Labels: Core Java, Java 8, Java 8 tutorial
4 Comments:
nice
Thanks Jatin.
Great!
Thanks Cassio.
Post a Comment
Subscribe to Post Comments [Atom]
<< Home