A Look at Java Optionals
Check out this post to learn more about Java Optionals.
Join the DZone community and get the full member experience.
Join For FreeOptional is a container object that may or may not contain a non-null value. If a value is present, isPresent()
will return true
and get()
will return the value.
Package : java.util
public final class Optional<T>
extendsObject
The following is a list of useful methods in the Optional
class:
1. Create Optional-Related Methods
Methods: Optional.of
, Optional.ofNullable
, Optional.empty()
:
Optional<String> emptyOptional = Optional.empty();
Optional<String> nonEmptyOptional = Optional.of("name"); // this will not work with null value
Optional<String> nonEmptyOptional = Optional.ofNullable(null); // this will work fine with null value
2. Check the Optional Value
Methods: Optional.isPresent()
, Optional.ifPresent()
-
isPresent()
returns true ifOptional
has values.
Optional<String> nonEmptyOptional = Optional.of("name");
assertTrue(nonEmptyOptional.isPresent());
-
ifPresent()
= execute a block of code if the value is present.
We have the following null value check inside the method before Optional
.
if(data == null){
System.out.println( " data is " + data);
}
// data is object used inside method
In this way, when it comes to null check, we cannot guarantee that "data" will not be used without null check, and it can cause NullPointerException
, if checks are not added before using it.
Now, with this Optional introduction, we can use ifPresent
for similar needs.
Optional<String> nonEmptyOptional = Optional.of("name");
nonEmptyOptional.ifPresent( x-> {System.out.println(x.length());});
3. Get Value From Optional
and Related Methods
-
get()
= returns value wrapped inOptional
.
Optional<String> nonEmptyOptional = Optional.ofNullable("orignal");
String value = nonEmptyOptional.get();
-
orElse()
= return a default value if value not present
// orElse getting used as Optional has null value.
Optional<String> emptyOptional = Optional.ofNullable(null);
String value = emptyOptional.orElse("default Value");
assertEquals("default Value", value);
// orElse not getting used as Optional has non null value.
Optional<String> nonEmptyOptional = Optional.ofNullable("orginal");
String value1 = nonEmptyOptional.orElse("default Value");
assertEquals("orginal", value1);
-
orElseGet()
= this is similar toorElse()
. Just instead of taking value, it takes the supplier function as the input when a value is not present inOptional
.
// orElse getting used as Optional has null value.
Optional<String> emptyOptional = Optional.ofNullable(null);
String value = emptyOptional.orElseGet(()->"default value");
assertEquals("default value", value);
// orElse not getting used as Optional has non null value.
Optional<String> nonEmptyOptional = Optional.ofNullable("orginal");
String value1 = nonEmptyOptional.orElseGet(()->"default value");
assertEquals("orginal", value1);
-
orElseThrow()
= Similar toorElseGet
; it throws an exception in cases where values are null.
@Test(expected = NullPointerException.class)
public void OrElseThrowCheck() {
String nullName = null;
String value = Optional.ofNullable(nullName).orElseThrow(
NullPointerException::new);
}
4. Optional Usage
- Using
Optional
as a return value.
One common usage of Optional
is to return an Optional
wrapper from a method. When you define a method, it can return the null value or Object based on method logic. It is a good approach to return the Optional
Object so that while using a method, the developer knows that the return value can be null. It forces the developer to handle a return Object gracefully. The beauty of the Optional
class is that it guides users to do proper checks and avoid NullPointerException
.
The following example defines the method "Optional<Employee>getEmployeeWithId(int id),
" which returns Optional<Employee>
, and the caller function has to use one of the Optional
methods to get the value, and in process, it makes sure that NullPointerExceptions
are avoided.
static List<Employee> employess = new ArrayList<>();
public static void main(String[] args) throws EmployeeNotFoundException {
employess.add(new Employee("emp1", 1, 1000));
employess.add(new Employee("emp2", 2, 2000));
employess.add(new Employee("emp1", 3, 3000));
Optional<Employee> employee = getEmployeeWithId(1);
Employee e = employee.orElseThrow(() -> new EmployeeNotFoundException("emp not found"));
System.out.println(e);
}
public static Optional<Employee> getEmployeeWithId(int id) {
Optional<Employee> employee = employess.stream().filter(e -> (e.getId() == id)).findFirst();
return employee;
}
- Using
Optional
as an argument to a method.
It is not advisable, nor correct, to use Optional
as an argument to the method. Suppose we have a method that takes two arguments: One is Optional
and one is non- Optional
. The idea behind using Optional
as one argument can be to support the null value of the Optional
argument.
Use the overloaded method instead of using Optional
an argument to the method.
Instead of using Optional
as an argument to support the null value of that argument, it is best to define one more overloaded method without the second argument.
public static Optional<Employee> getEmployee(int id,Optional<String> name) {
............
return employee;
}
//Better approach - User overloaded methods
public static Optional<Employee> getEmployee(int id,String name)
public static Optional<Employee> getEmployee(int id)
5. List of New Methods Added to Optional Class in Newer Java Versions
- Java 9
-
or()
— If a value is present, it returns anOptional
describing the value; otherwise, it returns anOptional
produced by the supplying function. -
ifPresentOrElse(Consumer<? super T>action, Runnable emptyAction)
— If a value is present, performs the given action with the value, otherwise performs the given empty-based action. -
stream()
— If a value is present, it returns a sequential Stream containing only that value; otherwise, it returns an empty Stream.
-
- Java 10
-
orElseThrow()
— If a value is present, it returns the value; otherwise, it throws aNoSuchElementException
. It does not accept any argument as Java version 8.
-
- Java 11
-
isEmpty()
— If a value is not present, it returns true; otherwise, it is false.
-
6. Complete Source Code
Please use following Git link to refer source code.
Note : Optional is a value-based class; use of identity-sensitive operations (including reference equality (==
), identity hash code, or synchronization) on instances of Optional
may have unpredictable results and should be avoided.
7. References
Below are the Java docs for various versions:
Published at DZone with permission of Dharmendra Rathor. See the original article here.
Opinions expressed by DZone contributors are their own.
Comments