In this article, we will discuss Optional class in detail and understand why it is needed/introduced in Java 1.8 version and how to avoid/handle (or to get rid of) the infamous NullPointerException which comes under the umbrella of Runtime Exception
1. Optional class :
- This is the new class introduced in Java 1.8 version to handle/avoid the infamous NullPointerException swiftly but altogether NullPointerException can’t be avoided
- So, what is Optional class in Java 1.8 and why it is needed ?
- It is a wrapper class for the actual object or in other words container for the actual object
- This way actual object will be wrapped inside Optional class
- With the help of predefined APIs (or methods) of Optional class, it is possible to get the actual object safely thereby avoiding the NullPointerException but then completely not ignoring any kind of Exception that may be arise/thrown
- In addition to this, there can be many more operations can be performed on the Optional in case of null like,
- Returning alternative value
- Or throwing predefined or custom exception with proper error message
- Let’s see different ways to create Optional in the following section
2. Different ways to create Optional :
There are 3 different ways (or static methods) available to create Optional as mentioned below –
- Optional.of();
- Optional.ofNullable();
- Optional.empty();
Note: all the above methods are static and can be accessed in a static way like <class-name>.<static-method>();
Let’s us understand each method in the mentioned order to understand their differences and usages in different scenarios
2.1 Optional.of(T) :
- This static method returns an
Optional
with the specified present non-null value- If the value present is non-null then it returns Optional[non-null-value]
- If the value present is null then it throws NoSuchElementException with the error message stating “No value present“
OptionalDemo1.java
package in.bench.resources.optional.demo;
import java.util.Optional;
public class OptionalDemo1 {
public static void main(String[] args) {
// Optional of
Optional<String> optionalOf = Optional.of("BenchResources");
System.out.println("Optional.of() :- " + optionalOf);
// try to get the value from Optional of
String str = optionalOf.get();
System.out.print("\nString value from Optional.of() using get() method :- " + str);
}
}
Output :
Optional.of() :- Optional[BenchResources]
String value from Optional.of() using get() method :- BenchResources
OptionalDemo2.java
package in.bench.resources.optional.demo;
import java.util.Optional;
public class OptionalDemo2 {
public static void main(String[] args) {
// Optional of
Optional<String> optionalOf = Optional.of(null);
System.out.println("Optional.of() :- " + optionalOf);
}
}
Output :
Exception in thread "main" java.lang.NullPointerException
at java.util.Objects.requireNonNull(Objects.java:203)
at java.util.Optional.<init>(Optional.java:96)
at java.util.Optional.of(Optional.java:108)
at in.bench.resources.optional.demo.OptionalDemo.main(OptionalDemo.java:10)
2.2 Optional.ofNullable(T) :
- This static method returns an
Optional
describing the specified value, if non-null, otherwise returns an emptyOptional
- If the value present is non-null then it returns Optional[non-null-value]
- If the value present is null then it returns Optional.empty without throwing any Exception like in the case of Optional.of(T)
- But when Optional.get() method is invoked to retrieve the value from the empty Optional then it throws NoSuchElementException with the error message stating “No value present“
OptionalDemo3.java
package in.bench.resources.optional.demo;
import java.util.Optional;
public class OptionalDemo3 {
public static void main(String[] args) {
// Optional ofNullable
Optional<String> optionalOfNullable = Optional.ofNullable("BenchResources");
System.out.println("Optional.ofNullable() :- " + optionalOfNullable);
// try to get the value from Optional ofNullable
String str = optionalOfNullable.get();
System.out.print("\nString value from Optional.ofNullable() "
+ "using get() method :- " + str);
}
}
Output :
Optional.ofNullable() :- Optional[BenchResources]
String value from Optional.ofNullable() using get() method :- BenchResources
OptionalDemo4.java
package in.bench.resources.optional.demo;
import java.util.Optional;
public class OptionalDemo4 {
public static void main(String[] args) {
// Optional ofNullable
Optional<String> optionalOfNullable = Optional.ofNullable(null);
System.out.println("Optional.ofNullable() :- " + optionalOfNullable);
// try to get the value from Optional ofNullable
String str = optionalOfNullable.get();
System.out.print("\nString value from Optional.ofNullable() "
+ "using get() method :- " + str);
}
}
Output :
Optional.ofNullable() :- Optional.empty
Exception in thread "main" java.util.NoSuchElementException: No value present
at java.util.Optional.get(Optional.java:135)
at in.bench.resources.optional.demo.OptionalDemo.main(OptionalDemo.java:15)
2.3 Optional.empty() :
- This static method returns an empty
Optional
instance - No value is present for this Optional
- It is just an empty container to represent Optional with no value
- If we try to get the value from the empty Optional (or Optional.empty) then it throws NoSuchElementException with the error message stating “No value present“
OptionalDemo5.java
package in.bench.resources.optional.demo;
import java.util.Optional;
public class OptionalDemo5 {
public static void main(String[] args) {
// empty Optional
Optional<String> emptyOptional = Optional.empty();
System.out.println("Optional.empty() :- " + emptyOptional);
}
}
Output :
Optional.empty() :- Optional.empty
OptionalDemo6.java
package in.bench.resources.optional.demo;
import java.util.Optional;
public class OptionalDemo6 {
public static void main(String[] args) {
// empty Optional
Optional<String> emptyOptional = Optional.empty();
System.out.println("Optional.empty() :- " + emptyOptional);
// try to get the value from empty Optional
String str = emptyOptional.get();
System.out.print("\nString value from Optional.empty() "
+ "using get() method :- " + str);
}
}
Output :
Optional.empty() :- Optional.empty
Exception in thread "main" java.util.NoSuchElementException: No value present
at java.util.Optional.get(Optional.java:135)
at in.bench.resources.optional.demo.OptionalDemo.main(OptionalDemo.java:15)
3. Getting value from Optional :
- To get the value from the Optional, instance method get() can be used which returns –
- value if present inside the Optional
- otherwise throws NoSuchElementExcption for null or Optional.empty
OptionalDemo7.java
package in.bench.resources.optional.demo;
import java.util.Optional;
public class OptionalDemo7 {
public static void main(String[] args) {
// empty Optional
Optional<String> optional = Optional.of("Java");
System.out.println("Optional.of(\"Java\") :- " + optional);
// try to get the value from Optional
String str = optional.get();
System.out.print("\nString value from Optional.of(\"Java\") "
+ "using get() method :- " + str);
}
}
Output :
Optional.of("Java") :- Optional[Java]
String value from Optional.of("Java") using get() method :- Java
OptionalDemo8.java
package in.bench.resources.optional.demo;
import java.util.Optional;
public class OptionalDemo8 {
public static void main(String[] args) {
// empty Optional
Optional<String> optional = Optional.ofNullable(null);
System.out.println("Optional.ofNullable(null) :- " + optional);
// try to get the value from Optional
String str = optional.get();
System.out.print("\nString value from Optional.ofNullable(null) "
+ "using get() method :- " + str);
}
}
Output :
Optional.ofNullable(null) :- Optional.empty
Exception in thread "main" java.util.NoSuchElementException: No value present
at java.util.Optional.get(Optional.java:135)
at in.bench.resources.optional.demo.OptionalDemo.main(OptionalDemo.java:15)
4. isPresent() & ifPresent() methods :
There are 2 instance methods available in Optional which helps to check if there exists any value in the Optional, those are,
- isPresent()
- This method returns
true
if there is a value present, otherwisefalse
- This method returns
- ifPresent()
- If a value is present, invoke the specified consumer with the value, otherwise do nothing
OptionalIsPresentDemo.java
package in.bench.resources.optional.demo;
import java.util.Optional;
public class OptionalIsPresentDemo {
public static void main(String[] args) {
// Optional 1
Optional<String> optional1 = Optional.of("BenchResources");
checkForValue(optional1);
// Optional 2
Optional<String> optional2 = Optional.ofNullable(null);
checkForValue(optional2);
// Optional 3
Optional<String> optional3 = Optional.empty();
checkForValue(optional3);
}
/**
* This method tests whether there exists any value in Optional or not
*
* @param optional
*/
private static void checkForValue(Optional<String> optional) {
if(optional.isPresent()) {
System.out.println("Value is present");
}
else {
System.out.println("Either empty or null");
}
}
}
Output :
Value is present
Either empty or null
Either empty or null
OptionalIfPresentDemo.java
package in.bench.resources.optional.demo;
import java.util.Optional;
public class OptionalIfPresentDemo {
public static void main(String[] args) {
// Optional 1
Optional<String> optional1 = Optional.of("BenchResources");
optional1.ifPresent(opt -> System.out.println("Value is present for the " + opt));
// Optional 2
Optional<String> optional2 = Optional.ofNullable(null);
optional2.ifPresent(opt -> System.out.println("Value is present for the " + opt));
// Optional 3
Optional<String> optional3 = Optional.empty();
optional3.ifPresent(opt -> System.out.println("Value is present for the " + opt));
}
}
Output :
Value is present for the BenchResources
5. Alternate way – return value or throw Exception :
There are 3 instance methods available in Optional which helps to return alternate value or throw custom exception in case value is not present in the Optional
- orElse()
- This method returns the value if present, otherwise return
value provided in the orElse
- This method returns the value if present, otherwise return
- orElseGet()
- This method returns the value if present, otherwise invoke
provided supplier
and return the result of that invocation
- This method returns the value if present, otherwise invoke
- orThrow()
- This method returns the contained value, if present, otherwise throw an exception to be created by the provided supplier
OptionalOrElseDemo.java
package in.bench.resources.optional.demo;
import java.util.Optional;
public class OptionalOrElseDemo {
public static void main(String[] args) {
// test string 1
String str = "BenchResources";
// Optional 1
String optional1 = Optional.of(str).orElse(dummy());
System.out.println("When Optional is not null :- " + optional1 + "\n");
// test string 12
str = null;
// Optional 2
String optional2 = Optional.ofNullable(str).orElse(dummy());
System.out.print("When Optional is null :- " + optional2);
}
/**
* dummy method to return value for orElse
* @return
*/
private static String dummy(){
System.out.println("dummy method is called");
return "dummy value";
}
}
Output :
dummy method is called
When Optional is not null :- BenchResources
dummy method is called
When Optional is null :- dummy value
OptionalOrElseGetDemo.java
package in.bench.resources.optional.demo;
import java.util.Optional;
public class OptionalOrElseGetDemo {
public static void main(String[] args) {
// test string 1
String str = "BenchResources";
// Optional 1
String optional1 = Optional.of(str).orElseGet(() -> dummy());
System.out.println("When Optional is not null :- " + optional1 + "\n");
// test string 12
str = null;
// Optional 2
String optional2 = Optional.ofNullable(str).orElseGet(() -> dummy());
System.out.print("When Optional is null :- " + optional2);
}
/**
* dummy method to return value for orElse
* @return
*/
private static String dummy(){
System.out.println("dummy method is called");
return "dummy value";
}
}
Output :
When Optional is not null :- BenchResources
dummy method is called
When Optional is null :- dummy value
OptionalOrThrowDemo.java
package in.bench.resources.optional.demo;
import java.util.Optional;
public class OptionalOrThrowDemo {
public static void main(String[] args) throws Exception {
// test string 1
String str = "BenchResources";
// Optional 1
String optional1 = Optional.of(str).orElseThrow(Exception::new);
System.out.println("When Optional is not null :- " + optional1 + "\n");
// test string 2
str = null;
// Optional 2
String optional2 = Optional.ofNullable(str).orElseThrow(Exception::new);
System.out.print("When Optional is null :- " + optional2);
}
}
Output :
When Optional is not null :- BenchResources
Exception in thread "main" java.lang.Exception
at java.util.Optional.orElseThrow(Optional.java:290)
at in.bench.resources.optional.demo.OptionalOrThrowDemo.main(OptionalOrThrowDemo.java:21)
6. Difference between orElse() & orElseGet() :
- The main difference between these 2 instance methods is how they deal with the invocation of the alternate method when the actual object wrapped around Optional is found to be null
- In case of orElse() method, the supplied method is invoked even when the value of actual object is not null although it isn’t required; whereas for orElseGet() method, supplied method won’t get invoked if there is a value present
- So, performance-wise orElseGet() method does a better job when comparing with orElse() method
- Method-signature of both methods slightly differs
- orElseGet() method accepts Supplier Functional interface
- orElse() method accepts value/object of same-type of Optional
public T orElseGet(Supplier<? extends T> other);
public T orElse(T other);
- Usage of both methods also differs like
- orElseGet() can only be used when there is Supplier function available
- whereas orElse() can be supplied with alternate value/object of same type of Optional
7. Mapping & Filtering Optional :
There are 2 instance methods available namely map() and filter() which helps to convert/transform and filter values from Optional
- map() – If a value is present, apply the provided mapping function to it, and if the result is non-null, return an
Optional
describing the result. Otherwise return an emptyOptional
public <U> Optional<U> map(Function<? super T,? extends U> mapper);
- filter() – If a value is present, and the value matches the given predicate, return an
Optional
describing the value, otherwise return an emptyOptional
public Optional<T> filter(Predicate<? super T> predicate);
OptionalMappingDemo.java
package in.bench.resources.optional.demo;
import java.util.Optional;
public class OptionalMappingDemo {
public static void main(String[] args) {
// Optional 1
Optional<String> optional1 = Optional.of("BenchResources.Net");
// map to upper case
String url = optional1.map(String::toUpperCase).orElse("default url");
System.out.println("Tranformed URL :- " + url);
// Optional 2
Optional<String> optional2 = Optional.ofNullable(null);
// map to upper case
url = optional2.map(String::toUpperCase).orElse("default url");
System.out.print("\nTranformed URL :- " + url);
}
}
Output :
Tranformed URL :- BENCHRESOURCES.NET
Tranformed URL :- default url
OptionalFilteringDemo.java
package in.bench.resources.optional.demo;
import java.util.Optional;
public class OptionalFilteringDemo {
public static void main(String[] args) {
// Optional 1
Optional<String> optional1 = Optional.of("BenchResources.Net");
// map to upper case
String url = optional1.filter(str -> str.startsWith("Bench")).orElse("default url");
System.out.println("URL :- " + url);
// Optional 2
Optional<String> optional2 = Optional.ofNullable(null);
// map to upper case
url = optional2.filter(str -> str.startsWith("Bench")).orElse("default url");
System.out.print("\nURL :- " + url);
}
}
Output :
URL :- BenchResources.Net
URL :- default url
Related Articles :
- Java 8 – Remove input-ted Character from a given String
- Java 8 – How to split a String and Collect to any Collection ?
- Java 8 – How to check whether given String contains only Alphabets or Letters ?
- Java 8 – How to check whether given String contains only Digits ?
- Java 8 – How to check whether given String contains Alphanumeric characters only ?
- Java 8 – How to convert first character of every word to Uppercase ?
- Java 8 – How to convert duplicate characters to Uppercase in a String ?
- Java 8 – How to remove special characters from String ?
- Java 8 – How to remove last comma (,) from String ?
- Java 8 – How to count length of last word in a String ?
References:
- https://docs.oracle.com/javase/8/docs/api/java/util/Optional.html
- https://docs.oracle.com/javase/8/docs/api/java/util/stream/Stream.html
Happy Coding !!
Happy Learning !!