Java 8 introduced Optional class which is used to manipulate data based on whether a value is present or absent. You can have the same functionality without using this class, however you would end up with way messier code. In other words, you will have less null checks and no NullPointerException’s.
Let me give you an example of why not using Optional could lead to problems.
Not using Optional
public class NonOptionalImplementation { public static void main(String[] args) { Animal dog = new Animal(null, 5); String dogModified = dog.getName().toLowerCase(); System.out.println(dogModified); } } class Animal { private String name; private int age; Animal(String n, int a) { this.name = n; this.age = a; } public String getName() { return this.name; } public int getAge() { return this.age; } }
Can you spot where this will go wrong? It is clear that when we get to the print statement, it will throw a NullPointerException as the name of the object is set to null (purposely).
Output
Exception in thread "main" java.lang.NullPointerException at OptionalImplementation.main(OptionalImplementation.java:6)
Fixing this issue with Optional
import java.util.Optional; import java.util.*; public class OptionalImplementation { public static void main(String[] args) { Animal dog = new Animal(null, 5); System.out.println(Optional.ofNullable(dog.getName()).orElse("Name not provided")); } } class Animal { private String name; private int age; Animal(String n, int a) { this.name = n; this.age = a; } public String getName() { return name; } public int getAge() { return this.age; } }
Output
Name not provided
A brief breakdown of the above implementation
- We are creating a very simple class called Animal and we have 2 getter methods with a constructor
- In our main method we are creating an instance of that Animal class, however we are also assigning the first argument, which happens to be the name, to null
- Optional.ofNullable checks whether the string passed is null or not
- After that we are trying to print the value
- We have this .orElse() method call which basically means: if the string you are calling this method on is null, then I will print in whatever is given as an argument
- If it is not null, then I will print the original string
- In other words, it prints a default value if the string is null
Cool isn’t it? Just look how elegant our code looks like when we are checking for null values. And safe as well!
For comparison, let’s try to get the same result without using the Optional class.
public class OptionalImplementation { public static void main(String[] args) { Animal dog = new Animal(null, 5); if (dog.getName() == null) { System.out.println("Name not provided"); } else { System.out.println(dog.getName().toLowerCase()); } } } class Animal { private String name; private int age; Animal(String n, int a) { this.name = n; this.age = a; } public String getName() { return this.name; } public int getAge() { return this.age; } }
Output
Name not provided
It works.. but is it clean? I don’t think so!
You can also use the method isPresent() to check if there is a value in an object:
import java.util.Optional; public class OptionalImplementation { public static void main(String[] args) { Optional<Object> n = Optional.empty(); // creating an empty string System.out.println(n.isPresent()); System.out.println(n); } }
Output
false Optional.empty
That’s it. Not so hard, is it? Not even it is very easy to understand but it also simplifies your code a lot and is very easy to read and maintainable as well. If you want to explore all methods that Optional provides, check the official Oracle documentation.