Aayush: weblog

Archive for March, 2019

Eliminating Null Pointer Exceptions from your Java Applications

Posted by Aayush Bhatnagar on March 31, 2019


This post is a brief introduction to one of the most useful yet “un-glamorous” features of Java 8.

Programmers have spent endless hours trying to rectify one of the most common errors yet the most dangerous – namely, Null Pointer Exceptions.

Null pointer exceptions can cause unexpected outages in our applications, and are very difficult to detect up-front.

On many occasions, when we use external libraries and APIs, the null pointers may come due to the value returned from the library/API.

Due to this reason, exception handling and the logical recovery from the exception becomes a complicated task for the programmer.

This involves a senior programmer to review the code, and define control flows for error recovery.

With Java 8, a new API has been added – namely, the “Optional” class to help developers create a framework for avoiding null pointers altogether, as well as to define the 1st level exception recovery policy for their applications.

Plainly stated –

The Optional API provides a container class which can be used to wrap return values of method invocations – even if they contain a “null” value.

It further provides APIs which enable the programmer to define the default value to return in case a “null” has been encountered. This forces the developer to think of a mitigation strategy for null values at the time of coding.

Null checks can be performed in two ways – through the “isPresent” and “ifPresent” methods.

When we invoke “isPresent“, if a non-null value is present, “true” would be returned.

On the other hand, apart from just checking whether the value is non-null, if we wish to delegate the control flow to another class in the same API call, then we can use the “ifPresent” method.

This method takes an argument of type “Consumer” – which is essentially a functional interface. This interface can be implemented by a class in your application.

Whenever “ifPresent” is called, we have to pass an implementation of the Consumer interface, so that control flow delegation can be done automatically.

From a developer’s standpoint – the consumer’s implementation can define the action to take when a non-null value is present.

There are some other useful features of this class, which programmers can use to avoid boiler plate code.

The filter function accepts an argument of type Predicate. If the return value matches the predicate, then the filtered value is returned otherwise an empty Optional object is returned.

On similar lines, we have other functions which can be invoked to organise the return values. Consider the map function and the flatmap function.

Both these functions are used to create a map of key-value pairs for the return value if it is present.

The developers also get the luxury to define the return values based on the evaluation of a logical criteria.

For example, consider the following functions –

orElse function returns the supplied value in the argument if the return value is null

orElseGet returns the value if present. Else if absent, it invokes the argument of type Supplier to return a custom value.

orElseThrow enables fine grained control over exception handling. If the return value is absent, a custom exception can be thrown, or the control flown can be delegated to a Supplier type – which in turn can decide what exception to throw.

In summary, with this API – we can reap benefits across the software development lifecycle

Software Architects can cut down on code review cycles, by standardising exception handling.

QA engineers would have lesser bugs to report which are caused by null pointer exceptions

Software designers can think through their exception handling logic up front and avoid silly patching later on.

Developers would end up writing more effective code reducing time to market.

Advertisements

Posted in Uncategorized | Leave a Comment »