Ernest is a Java developer. Outside programming, he also enjoys a wide variety of hobbies which includes sky-diving, photography, exercising and listening to music.

At IDR Solutions we use Java 8 for the development of our products (a Java PDF Viewer and SDK, PDF to HTML5 converter and a Java ImageIO replacement). This time we will be looking at the Optional Class.

What is this Optional

It is simply a container that may contain some value or may contain a non-null value and it is primarily intended for use in streams. It has a method isPresent() which will return true when a value is present and a method called get() which will returns the value present. So this basically helps alleviate Null Pointer Exception.

You can already implement this functionality with null checks. It was added into Java8 to allow developers to write more ‘elegant’ code which is easier to read and can potentially be processed in parallel in Java.

Lets have a look at this code below:

import java.util.ArrayList ; import java.util.List ; /** * * */ public class Course { private List modules = new ArrayList ( ) ; public void addModule ( Module module ) { modules. add ( module ) ; } public List getModules ( ) { return modules ; } } class Module { private Student students ; private String moduleName ; public Module ( String moduleName ) { this . moduleName = moduleName ; } public String getModuleName ( ) { return moduleName ; } public Student getStudent ( ) { return students ; } public void setStudents ( Student students ) { this . students = students ; } } class Student { private int numberOfStudents ; public Student ( int number ) { this . numberOfStudents = number ; } public int getNumberOfStudents ( ) { return numberOfStudents ; } public void setNumberOfStudents ( int numberOfStudents ) { this . numberOfStudents = numberOfStudents ; } public static void main ( String [ ] args ) { // TODO code application logic here Course computerScience = new Course ( ) ; Module algorithms = new Module ( "Algorithms" ) ; Student studentsOnAlgorithm = new Student ( 50 ) ; algorithms. setStudents ( studentsOnAlgorithm ) ; computerScience. addModule ( algorithms ) ; computerScience. getModules ( ) . stream ( ) . forEach ( ( m ) -& gt ; { System . out . println ( "Module ---> " + m. getModuleName ( ) + "

" + m. getStudent ( ) . getNumberOfStudents ( ) + " students take this module" ) ; } ) ; } } import java.util.ArrayList; import java.util.List; /** * * */public class Course { private List modules = new ArrayList(); public void addModule(Module module){ modules.add(module); } public List getModules() { return modules; } } class Module{ private Student students; private String moduleName; public Module(String moduleName){ this.moduleName = moduleName; } public String getModuleName() { return moduleName; } public Student getStudent() { return students; } public void setStudents(Student students) { this.students = students; } } class Student{ private int numberOfStudents; public Student(int number){ this.numberOfStudents = number; } public int getNumberOfStudents() { return numberOfStudents; } public void setNumberOfStudents(int numberOfStudents) { this.numberOfStudents = numberOfStudents; } public static void main(String[] args) { // TODO code application logic here Course computerScience = new Course(); Module algorithms = new Module("Algorithms"); Student studentsOnAlgorithm = new Student(50); algorithms.setStudents(studentsOnAlgorithm); computerScience.addModule(algorithms); computerScience.getModules().stream().forEach((m) -> { System.out.println("Module ---> "+m.getModuleName() + "

"+ m.getStudent().getNumberOfStudents()+" students take this module"); }); } }

Output

Module —> Algorithms

50 students take this module

This code works perfect. Now lets say we have a module which has been discontinued teaching but still in the list of Course with no students attached to it.

public static void main ( String [ ] args ) { // TODO code application logic here Course computerScience = new Course ( ) ; Module algorithms = new Module ( "Algorithms" ) ; Student studentsOnAlgorithm = new Student ( 50 ) ; algorithms. setStudents ( studentsOnAlgorithm ) ; computerScience. addModule ( algorithms ) ; Module cancelledModules = new Module ( "Pascal" ) ; computerScience. addModule ( cancelledModules ) ; computerScience. getModules ( ) . stream ( ) . forEach ( ( m ) -& gt ; { System . out . println ( "Module ---> " + m. getModuleName ( ) + "

" + m. getStudent ( ) . getNumberOfStudents ( ) + " students take this module" ) ; } ) ; } } public static void main(String[] args) { // TODO code application logic here Course computerScience = new Course(); Module algorithms = new Module("Algorithms"); Student studentsOnAlgorithm = new Student(50); algorithms.setStudents(studentsOnAlgorithm); computerScience.addModule(algorithms); Module cancelledModules = new Module("Pascal"); computerScience.addModule(cancelledModules); computerScience.getModules().stream().forEach((m) -> { System.out.println("Module ---> "+m.getModuleName() + "

"+ m.getStudent().getNumberOfStudents()+" students take this module"); }); } }

Output

Module —> Algorithms

50 students take this module Exception in thread “main” java.lang.NullPointerException

Now lets Use the Optional Rectify the problem

public class Course { private List modules = new ArrayList ( ) ; public void addModule ( Module module ) { modules. add ( module ) ; } public List getModules ( ) { return modules ; } } class Module { private Optional students = Optional. empty ( ) ; private String moduleName ; public Module ( String moduleName ) { this . moduleName = moduleName ; } public String getModuleName ( ) { return moduleName ; } public Optional getStudent ( ) { return students ; } public void setStudents ( Optional students ) { this . students = students ; } } class Student { private int numberOfStudents ; public Student ( int number ) { this . numberOfStudents = number ; } public int getNumberOfStudents ( ) { return numberOfStudents ; } public void setNumberOfStudents ( int numberOfStudents ) { this . numberOfStudents = numberOfStudents ; } public static void main ( String [ ] args ) { // TODO code application logic here Course computerScience = new Course ( ) ; Module algorithms = new Module ( "Algorithms" ) ; Optional studentsOnAlgorithm = Optional. of ( new Student ( 50 ) ) ; algorithms. setStudents ( studentsOnAlgorithm ) ; computerScience. addModule ( algorithms ) ; Module cancelledModules = new Module ( "Pascal" ) ; computerScience. addModule ( cancelledModules ) ; computerScience. getModules ( ) . stream ( ) . forEach ( ( m ) -& gt ; { if ( m. getStudent ( ) . isPresent ( ) ) { System . out . println ( "Module ---> " + m. getModuleName ( ) + "

" + m. getStudent ( ) . get ( ) . getNumberOfStudents ( ) + " students take this module" ) ; } else { System . out . println ( "Module ---> " + m. getModuleName ( ) + "

has no students attached to it" ) ; } } ) ; } } public class Course { private List modules = new ArrayList(); public void addModule(Module module){ modules.add(module); } public List getModules() { return modules; } } class Module{ private Optional students = Optional.empty(); private String moduleName; public Module(String moduleName){ this.moduleName = moduleName; } public String getModuleName() { return moduleName; } public Optional getStudent() { return students; } public void setStudents(Optional students) { this.students = students; } } class Student{ private int numberOfStudents; public Student(int number){ this.numberOfStudents = number; } public int getNumberOfStudents() { return numberOfStudents; } public void setNumberOfStudents(int numberOfStudents) { this.numberOfStudents = numberOfStudents; } public static void main(String[] args) { // TODO code application logic here Course computerScience = new Course(); Module algorithms = new Module("Algorithms"); Optional studentsOnAlgorithm = Optional.of(new Student(50)); algorithms.setStudents(studentsOnAlgorithm); computerScience.addModule(algorithms); Module cancelledModules = new Module("Pascal"); computerScience.addModule(cancelledModules); computerScience.getModules().stream().forEach((m) -> { if (m.getStudent().isPresent()) { System.out.println("Module ---> " + m.getModuleName() + "

" + m.getStudent().get().getNumberOfStudents() + " students take this module"); } else { System.out.println("Module ---> " + m.getModuleName() + "

has no students attached to it"); } }); } }

Output

Module —> Algorithms

50 students take this module

Module —> Pascal

has no students attached to it

In the Module class, we replaced the Student with an empty Optional object and also replaced the getter and setter method to return and set Optional Objects .

Also in the body of the for loop, we used the m.getStudent().isPresent() if there is a value then we use the m.getStudent().get().getNumberOfStudents() to get the value available.

Convenient Instance Methods On Optional

filter(Predicate predicate) This will return a value present only if it is present and that it matches a given predicate otherwise it will return an empty optional ifPresent() This will returns true if a value is present in the optional. ifPresent(Consumer consumer) This will invoke the specified consumer with the value, only if the value is present otherwise do nothing. get() This will returns the value in the Optional if present, otherwise throws NoSuchElementException. orElse(T other) This will return the value, if present, otherwise returns the value in other. orElseGet(Supplier other) This will return the value if present, otherwise invoke other and return the result of that invocation. orElseThrow(Supplier exceptionSupplier) This will return the value, if present otherwise throw an exception created by the provided supplier

If you found this article useful, you may also be interested in our other Java8 posts on Lambda Expression, Streams API, Default Methods, Method References and Repeating Annotations and Consumer Suppliers.

We also now have large collection of articles on what is new in other versions of Java, including Java9 , Java10, Java12 and OpenJDK.

Did you know...

IDRsolutions offers a whole range of online file converters to convert PDF and Microsoft Excel, Word and Office Documents to HTML5, SVG or image formats?

It is free to use for single file conversions and also includes Developer links if you want to use our commercial software for bulk conversions. Find out more on this page