Home Java Reduce NullPointerExceptions with Optional in Java

Reduce NullPointerExceptions with Optional in Java

Published: Last Updated on 0 comment

Hey, Tea Lovers! Today we will talk about the Optional class in Java 8. But before that, Did you know that Tony Hoare, The inventor of the null reference, has said that the null reference is his “Billion Dollar Mistake”? Since NullPointerException is the most common and frequently appeared error compared to others, especially for Java developers.


I would be happy to connect with you guys on social media. It’s @coderstea on TwitterLinkedinFacebook, Instagram, and YouTube.

Please Subscribe to the newsletter to know about the latest posts from CodersTea.


I have seen people wrapping each code block in a try-catch to handle this sneaky fool. That’s how much we are scared of this exception.

In most of the cases, a simple check is done like, obj !== null, Objects.isNull(obj). But in modern Java, from Java8, we have a new approach to handle the null object, or I would say, protecting us from NullPointerException. And that’s called Optional.

What is Optional In Java 8

Optional.java is a class in java.util the package that, as the name suggests, holds the optional value. This means, the value is optional and may or may not be present. It encapsulates your object and with multiple methods, it gives you the power to retrieve the object in various manners.

Optional has been introduced in Java8 and is used in various parts since then. If you look at the Stream API, it has used Optional in many cases. Spring JPA also returns Optional values for a single object. And you can also use it in your code. Let us look at how.

Create an Optional in Java

To create an Optional, you just have to use the Optional’s static method(s). It depends on what kind of object you are encapsulating. Let’s see them.

If your object is not null, then you can use Optional.of(obj). It returns the Optional of the object. But if your object is null, it will give you a NullPointerException. So you have to use Optional.ofNullable(obj) which will return an empty Optional. You can directly return an empty Optional with Optional.empty().

Optional<String> nonEmptyOptional = Optional.of("Not null");
System.out.println(nonEmptyOptional.isPresent()); //true
Optional<String> nullObject = Optional.ofNullable(null);
System.out.println(nullObject.isPresent()); //false empty optional
Optional<String> emptyOptional = Optional.empty();
System.out.println(emptyOptional.isEmpty()); //true  only work in Java 11 or aboveCode language: JavaScript (javascript)

Check Optional State

In the previous block, I used isPresent() for checking whether the optional object holds any value or is it empty. It will return true if it holds value i.e not a null object, otherwise, it returns false for empty Optionals. It is similar to checking whether the object is null or not. You can also use isEmpty(), introduced in Java 11, which is exactly the opposite of isPresent(). For empty Optional, it will return true otherwise false.

if(nonEmptyOptional.isPresent()){
    System.out.println("The value is present");
}
if(nullObject.isEmpty()){
    System.out.println("No value is not present");
}Code language: JavaScript (javascript)

Get the Value

OK, so we encapsulated the object into Optional. I have also checked for it. But How do I get the original value? Well, you can do so by calling get(). It will return the object from Optional. But beware, you shouldn’t be using the get() directly. Since it returns the value directly and if it has a null value it will throw an exception. So better to be used with isPresent() than go on with the get().

if (nonEmptyOptional.isPresent()) {
    System.out.println("The value " + nonEmptyOptional.get());
}
if (!nullObject.isPresent()) {
    System.out.println("No value is not present");
}Code language: JavaScript (javascript)

The above code, is OK but not so advantageous, we could have done it with a simple null check, right? There is a better way of handling things. There are quite a few depending on your requirement.

ifPresent(Consumer)

It is the combination of isPresent() and get(), but in a functional way. As the name suggests, do this if the value is present. It takes a Consumer as input. The Consumer will only be called if the value is present i.e non-null object. More about the Consumer here.

Optional<String> codersTea = Optional.of("coderstea.in");
nonEmptyOptional.ifPresent(site -> System.out.println("World's best website is " + site));
Optional<String> empty = Optional.empty();
empty.ifPresent(x -> System.out.println("No this will not run."));Code language: PHP (php)

Get Default Value if Empty

Now, what if you want to assign a default value if the object is null? You can do so by calling orElse(defaultObj). This way, if the Optional is empty defaultObj will be returned otherwise, the original value will be returned.

Optional<String> empty = Optional.empty();
String name = empty.orElse("Default Name"); //Default Name
String name1 = Optional.of("CodersTea").orElse("Default Name"); // CodersTeaCode language: JavaScript (javascript)

It’s a great approach, but the default object will be created every time you call the function regardless of empty optional. Since you are passing it as the value it is getting created eagerly. It is an unnecessary burden. Here’s how.

public static void main(String[] args) {
    Optional<String> empty = Optional.empty();
    String name = empty.orElse(printAndReturnDefaultName()); //Default Name
    String name1 = Optional.of("CodersTea").orElse(printAndReturnDefaultName()); // CodersTea
}
static String printAndReturnDefaultName(){
    System.out.println("Default Name");
    return "Default Name";
} Code language: JavaScript (javascript)

Output:

Default Name
Default NameCode language: PHP (php)

As you can see it is printed two times, even though it is needed for 1 time only. To overcome this, we can use the Functional Way. Here is how.

orElseGet(Supplier)

It takes in a Supplier as a parameter. Read more about Supplier in my post “Be More Functional with Java’s Functional Interfaces“. Since Functional programming is Lazy, It won’t be created until called. And that’s the major difference between orElse() which uses eager initialization of default object and orElseGet() which initializes lazily i.e when needed.

Optional<String> empty = Optional.empty();
String name = empty.orElseGet(() -> printAndReturnDefaultName()); //Default Name
String name1 = Optional.of("CodersTea").orElseGet(() -> printAndReturnDefaultName()); // CodersTea
String name2 = Optional.of("SuperHero").orElseGet(OptionalClass::printAndReturnDefaultName); //with method referenceCode language: JavaScript (javascript)

Output:

Default NameCode language: PHP (php)

As you can see, it is called only once for empty Optional.

orElseThrow()

Sometimes you can’t take it anymore and it’s enough. No more null value or you will burst out. To take out that frustration you can use is orElseThrow(). Does it take a Supplier<? extends Throwable> as a parameter and if the optional is empty throws the given Exception. You can use it if you can’t proceed without a value or any condition where a null object is not tolerated.

Optional.empty().orElseThrow(() -> new Exception("Provide me a Name, man"));
Optional.ofNullable(null). orElseThrow(FileNotFoundException::new);Code language: PHP (php)

Do More than Null Checks

Now that we have seen how it manages the null values let us see how it expands beyond null checks. Optional has more functions than listed above. Just like Stream API, you can create your pipeline with the Optional. The only difference is that Stream API works on Collection, while Optional is on the given Object. You can do the filter, map, flatMap, and many more. I have discussed this in my “Stream API: The Hero Without a Cape“. For now, I will go through the pipeline.

//lombok
@Data
@Builder
class Employee{
    private String name;
    private int age;
    private boolean isManager;
    private List<Integer> tasksIds;
    public static void main(String[] args) {
        //get the total task numbers if employee age gt 23
        Employee employee = Employee.builder()
                .age(23).name("Bob").isManager(false)
                .tasksIds(Arrays.asList(1,2,3,4))
                .build();
        int empGt20TaskCount = Optional.of(employee)
                .filter(e -> e.getAge() > 20)
                .map(Employee::getTasksIds)
                .map(List::size)
                .orElse(-1);
        System.out.println("Employee with age over 20 and its task count is " + empGt20TaskCount);
        //manager
        Employee manager = Employee.builder()
                .age(23).name("Bob").isManager(true)
                .tasksIds(Arrays.asList(1,2,3,4))
                .build();
        Optional.of(manager)
                .filter(e -> e.getAge() > 20)
                .filter(Employee::isManager)
                .map(Employee::getTasksIds)
                .map(List::size)
                .ifPresent(tasks -> System.out.println("Manger is having" + tasks + " tasks"));
        //if employee is not manager then throw error
        Optional.of(employee).filter(Employee::isManager).orElseThrow(() -> new Exception("IT must be manager"));
    }
}Code language: PHP (php)

As you can see, the code has become more declarative, and Optional is providing more than just a null value check. By the way, if you are wondering what the @Data or @Builder is check out my previous post on Lombok “Say Good-Bye to Boilerplate Code with Lombok: Part 1-Installation” and “Say Good-Bye to Boilerplate Code with Lombok: Part 2-The Code“.

Conclusion of Optional in Java

I think I have pretty much covered the Optional for Java 8. If you use this class then you will have much more flexibility in handling null values and may greatly decrease the possibility of NullPointerException. And it goes beyond null checks and provides you with Functional Programming experience. Please let me know in the comments how did you like the post or want any improvement in the content.

The examples used in this post can be found on GitHub here or the full project here

See you in the next post. HAKUNA MATATA!!!


I would be happy to connect with you guys on social media. It’s @coderstea on TwitterLinkedinFacebook, Instagram, and YouTube.

Please Subscribe to the newsletter to know about the latest posts from CodersTea.


Subscribe
Notify of
guest
0 Comments
Inline Feedbacks
View all comments
Ads
Ads
Ads

@2023 All Right Reserved. Designed and Developed by CodersTea

This website uses cookies to improve your experience. We'll assume you're ok with this, but you can opt-out if you wish. Accept Read More