Saturday 3 September 2016

Understanding and using Java 8 Optional class

Background

Java 8 has introduced a new class Optional which is kind of a container which may or maynot hold a value. You might ask whats the big deal? I might be as well and I might add null checks to avoid NPE. Think about it there is no clear way to suggest that null is a special value that can be returned whereas using Optional clearly indicates that the the value may not be present. Plus you can use functional programming with it - Lambdas and much more. Well see that in a moment.


To the code...

Let's see how we can use this in code - 

import java.util.Optional;
import java.util.function.Consumer;

public class Java8Demo {

    public static void main(String[] args) {
        
        Consumer<String> printer =  (str) -> System.out.println("Concat result : " + str);
        
        //case1 :
        String str1 = "abc";
        String str2 = "pqr";
        printer.accept(concat(Optional.of(str1), Optional.of(str2)));
        
        //case2 :
        str1 = "abc";
        str2 = null;
        printer.accept(concat(Optional.of(str1), Optional.ofNullable(str2)));
        
        //case3 :
        str1 = "abc";
        str2 = null;
        printer.accept(concat(Optional.of(str1), Optional.of(str2)));// WARN:NPE
    }
    
    public static String concat(Optional<String> str1, Optional<String> str2) {
        
        //isPresent()
        System.out.println("str1 present : " + str1.isPresent());
        System.out.println("str2 present : " + str2.isPresent());
        
        //ifPresent(Consumer c)
        str1.ifPresent(System.out::println);
        str2.ifPresent(System.out::println);
        
        //orElse(T other)
        String val1 = str1.orElse("");
        //orElseGet(Supplier s)
        String val2 = str1.orElseGet(() -> "");
        
        return val1 + val2;
        
    }

}

And the output is :

str1 present : true
str2 present : true
abc
pqr
Concat result : abcabc
str1 present : true
str2 present : false
abc
Concat result : abcabc
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 Java8Demo.main(Java8Demo.java:23)

as expected. 

Understanding


Method isPresent() is used to check if your Optional container has value or not. If it is there you can use get() method to retrieve it. Also notice how create a Optional instance. If it has to contain value you create it as Optional.of(value) other wise you use Optional.ofNullable(value) or Optional.empty(). Then you also have other useful methods like orElse(T other) which will return the value if it is present in Optional instance or return the argument supplied in method parameter. You have similar other methods - orElseGet(Supplier s), ifPresent(Consumer c), orElseThrow(Supplier s) that again uses functional programming. Have demoed most of them in code above. Others are similar and straightforward. You can see details of all methods in picture below.

 Details of all the methods of Optional class are as follows -


Other uses

You can also use this in Spring framework as follows -

If you are using Spring 4.1 and Java 8 you can use java.util.Optional which is supported in @RequestParam, @PathVariable, @RequestHeader and @MatrixVariable in Spring MVC -

@RequestMapping(value = {"/json/{type}", "/json" }, method = RequestMethod.GET)
public @ResponseBody TestBean typedTestBean(
    @PathVariable Optional<String> type,
    @RequestParam("track") String track) {      
    if (type.isPresent()) {
        //type.get() will return type value
        //corresponds to path "/json/{type}"
    } else {
        //corresponds to path "/json"
    }       
}

Related Links

t> UA-39527780-1 back to top