Optionals is a new feature added by Java 8. It helps to avoid unwanted NullPointerExceptions in code. In this article, we will be learning about Optionals and how they work.
- What is an Optional
- Creating an Optional
- Checking if a value is present in an Optional
- Retrieving Value from an Optional
- Operations on Optional
- Benefits of Optional
What is an Optional
Optional is a class that allows storing a value that may or may not be present. It is a generic class. So, the type of data that the Optional object contains can be specified via generic.
Sample Code
Optional op1; Optional op2; Optional op3;
- Line 1 declares an Optional op1 of type Integer
- Line 2 declares an Optional op2 of type String
- Line 3 declares an Optional op3 of type Person which is a custom class.
Creating an Optional
The Optional class has static methods that can be used to create an Optional.
Sample Code
Optional op1 = Optional.empty(); Optional op2 = Optional.of("Hello"); Optional op3 = Optional.ofNullable(100); Optional op4 = Optional.ofNullable(null);
- Line 1 creates op1 using Optional.empty method. This creates an empty Optional or an Optional without a value
- Line 2 creates op2 using the Optional.of method. This creates an Optional with the specified value (“Hello”). This method can only be used to create an Optional with a non-null value, so if a null value is specified as a parameter to this method a NullPointerException occurs.
- Line 3 creates op3 using the Optional.ofNullable method. This creates an Optional with the value 100. This method can be used to create an Optional with a null as well as non-null value.
- Line 4 creates op4 using the Optional.ofNullable method with a null value. This creates an empty Optional.
Checking if a value is present in an Optional
The Optional class has two methods called isEmpty and isPresent. These return a boolean value which indicates if a value is present in the Optional or not.
Sample Code
Optional op1 = Optional.empty(); System.out.println("Is empty:"+op1.isEmpty()); System.out.println("Is present:"+op1.isPresent()); Optional op2 = Optional.of("Hello"); System.out.println("Is empty:"+op2.isEmpty()); System.out.println("Is present:"+op2.isPresent());
- Line 1 creates op1 as an empty Optional
- Line 2 invokes the isEmpty method on op1 which returns true
- Line 3 invokes the isPresent method in op1 which returns false
- Line 4 creates op2 with the value “Hello”
- Lines 5-6 similarly invoke the isEmpty and isPresent methods on op2
Output
Is empty:true
Is present:false
Is empty:false
Is present:true
Retrieving Value from an Optional
The Optional class has many methods that can be used to retrieve a value from an Optional.
get
The get method returns the value in the Optional if present, otherwise it throws a NoSuchElementException
Sample code
Optional op1 = Optional.of("Hello"); System.out.println(op1.get()); Optional op2 = Optional.empty(); System.out.println(op2.get());
- Line 1 creates op1 with the value “Hello”.
- Line 2 invokes the get method which returns this value
- Line 3 creates op2 as an empty Optional
- Line 4 invokes get on op2 which throws a NoSuchElementException
Output
Hello
Exception in thread “main” java.util.NoSuchElementException: No value present
orElse
The orElse method returns the value in the Optional or the supplied default value in case the Optional is empty.
Sample Code
Optional op1 = Optional.of("Hello"); System.out.println(op1.orElse("default")); Optional op2 = Optional.empty(); System.out.println(op2.orElse("default"));
- Line 2 invokes the orElse method on op1. Since op1 has the value “Hello”, this is returned.
- Line 4 invokes the orElse method on op2. Since op2 is empty, the value “default” is returned.
Output
Hello
Default
orElseThrow
The Optional class has a method called orElseThrow. It returns the value in the optional if present otherwise throws a NoSuchElementException.
Sample Code
Optional op1 = Optional.of("Hello"); System.out.println(op1.orElseThrow()); Optional op2 = Optional.empty(); System.out.println(op2.orElseThrow());
- Line 2 invokes the orElseThrow method on op1. Since op1 has the value “Hello” this is returned.
- Line 4 invokes the orElseThrow method on op2. Since op2 is empty, an exception is thrown
Output
Hello
Exception in thread “main” java.util.NoSuchElementException: No value present
Operations on Optional
There are many methods on the Optional class that can be used to perform an operation on the value in the Optional.
ifPresent
The ifPresent method accepts as parameter a Consumer (which is an in-built functional interface). If a value is present in the Optional, it applies the action specified by the Consumer to the Optional. Otherwise, it does not do anything.
Sample Code
Optional op1 = Optional.of("Hello"); op1.ifPresent(str -> System.out.println(str)); Optional op2 = Optional.empty(); op2.ifPresent(str -> System.out.println(str));
- Line 2 invokes the ifPresent method on op1. A lambda expression is used which simply prints the input value. Since op1 has the value “Hello” this gets printed
- Line 4 invokes the ifPresent method on op2. Since op2 is empty, nothing happens, no action is performed.
Output
Hello
Filter
The filter method accepts as parameter a Predicate (which is an in-built functional interface) and applies the condition in the Predicate on the value in the Optional if present. If the condition is true, it returns an Optional with the same value, otherwise, it returns an empty Optional. If the input Optional is empty, it returns an empty Optional.
Sample Code
Optional op1 = Optional.of("Hello"); Optional result1 = op1.filter(str -> str.startsWith("H")); System.out.println(result1.isPresent()); Optional result2 = op1.filter(str -> str.startsWith("A")); System.out.println(result2.isPresent()); Optional op2 = Optional.empty(); Optional result3 = op2.filter(str -> str.startsWith("A")); System.out.println(result3.isPresent());
- Line 2 invokes the filter method on op1. A lambda expression is used which checks if the String in the optional starts with “H”. Since this is true, it returns an Optional with the value “Hello”
- Line 4 invokes the filter method on op1 with a lambda expression that checks if the String starts with “A”. Since this is false, filter returns an empty Optional
- Line 6 invokes the filter method on op2. Since op2 is empty, it returns an empty optional
Output
Benefits of Optional
The main benefit of the Optional class is that it prevents unwanted NullPointerExceptions. Without Optional, you need to add explicit checks for null values.
Sample Code
void doSomething(String input) { if(input != null) { input.toUpperCase(); } }
- This code specifies a method that accepts a String parameter
- Line 2 specifies an if statement that checks if the value is not null and if so, invokes the toUpperCase method on it
- So, without Optionals, you need to write an if statement that checks if a value is not null before performing an operation on it. If not, the code can cause a NullPointerException
This code can be rewritten using an Optional as follows:
private static void doSomething(Optional input) { input.ifPresent(str -> str.toUpperCase()); }
Line 2 invokes the ifPresent method on input. As seen earlier, the ifPresent method performs the specified operation if a value is present in the Optional, otherwise, it does not do anything. Thus, there is now no need to write an explicit if statement.
Conclusion
So, in this article, we learned what is an Optional and how to create it. We also saw how to check if an Optional has a value and how to retrieve the value from the Optional. We then took a look at some of the operations that can be performed on the Optional. Finally, we saw how Optionals avoid having to write explicit null checks in code.