Java 8 — Optional Class

Hasitha Hiran
3 min readFeb 5, 2023

--

Java 8 introduced the Optional class as a way to handle null values more elegantly. This new addition to the Java Standard Library has been a game-changer for developers, making it easier to write cleaner and more concise code. In this blog, we’ll be diving into the Optional class, exploring its capabilities, and discover how it can be used to write safer and more maintainable code.

Optional Object creation

  1. empty() method
Optional<String> optionalEmpty = Optional.empty();

2. of() method

User user = new User(10, null ,"0728288992");
Optional<String> firstName = Optional.of(user.getFirstName());

This method creates an Optional instance that contains a non-null value. If the value passed to of is null, a NullPointerException is thrown. In this example, it throws a NullPointerException.

3. ofNullable() method

Optional<String> firstName = Optional.ofNullable(user.getFirstName());

This method creates an Optional instance that contains either a non-null value or an empty Optional. This method is useful when we don’t know whether the value we’re passing is null or not. if the value is null, then this returns an empty optional and not returns a NullPointerException.

Checking Value Presence

The isPresent() and isEmpty() methods are the functions provided by the Optional class to check the presence of a value in an Optional object. These methods are helpful when we have to add conditions.

if(firstName.isPresent()){
// add logic here
System.out.println(firstNameOptional.get());
}

Default value set with orElse() and orElseGet() methods

These methods allow developers to provide a default value or a default value supplier in case the Optional object is empty. The main difference between the two methods is that orElse() returns a hard-coded default value, while orElseGet() returns the result of evaluating a Supplier functional interface. This can be useful for cases where the default value needs to be computed at runtime. In this article, we will discuss both of these methods in detail and understand how to use them effectively.

orElse() — if the value is null returns the default value both cases

String name = Optional.ofNullable(user1.getFirstName()).orElse("default value");

orElseGet()

String name = Optional.ofNullable(user1.getFirstName()).orElseGet(()-> "default name");

orElse() vs orElseGet()

 public static String setDefault() {
System.out.println("default logic executes");
return "default logic executes";
}
 String text = "default value";

String defaultTextElse = Optional.ofNullable(text).orElse(setDefault());
System.out.println("defaultTextElse "+defaultTextElse);

String defaultTextElseGet = Optional.ofNullable(text).orElseGet(() -> setDefault());
System.out.println("defaultTextElseGet "+defaultTextElseGet);

output

default logic executes
defaultTextElse value presents
defaultTextElseGet value presents

Above example, the value is non-null. when using orElseGet() to retrieve the wrapped value, the setDefault() method is not even invoked because the contained value is present.

orElse() method, whether the wrapped value is present or not, the default object is created. So in this case, we have just created one redundant object that is never used. We need to understand the difference between the two methods when we deal with more complex code otherwise performance wise can be affected.

orElseThrow()

The orElseThrow() method accepts a lambda expression or a supplier, which is used to generate the exception to be thrown in case the Optional instance is empty. We can set up general exceptions or custom exceptions for this.

 public static User getUserByUserIdOptional(String email) throws Exception {

// getAll() method sends all user from the database
List<User> users = getAll();

return users.stream()
.filter(user -> user.getEmail().equals(email))
.findFirst()
.orElseThrow(() -> new Exception("no customer present with this email"));
}

Above example, findFirst() is a terminal operation of Java streams and ideally returns the first element in a stream as an Optional type. according to the example, if the user is not present in the database, it throws a null pointer exception. to handle that we can use orElse(), orElseGet() or orElseThrow() based on the usecase.

These are some basic methods that we have to work with day to day. There are other methods as well and you can refer to this to get more information.

Thanks for reading.

--

--

Hasitha Hiran

Software Engineering Graduate at Sri Lanka Institute of Information Technology(SLIIT) || Software Engineer at WILEY