Introduction

In a developer life, we always have some places in the code where we test for an object to not be null before continuing a workflow or an action, it's safe to do it in order to avoid NullPointerException in Java. Kind of thing that can be made more simply now while resuing a particular JDK utility class that exists since 1.7.

Let's see in this write-up how we can achieve it in a more straightforward way.

Context

Personally, before acknowledging the existence of the Objects class I used to write the same lines of codes daily to test for a null object and throw a NPE or even rely on my own utility class to do so.

Now we can save more lines of codes because this approach is now shipped with the JDK since 1.7 and see by many developers as the standardized way of checking for crucial non-null objects. You can, for example, check its use on GitHub by this query.

We just need to be aware that here we're talking about the Objects class(with "s" at the end) not the famous parent Object class.

Let's say we're building a little SDK, and its entry point has some required parameters, that is the code we might write to catch that:

if(object == null) {
    throw new NullPointerException(message);
}

This was presents in a lot of places in our projects.

Check for Nullity with Objects class

The Objects class has a lot of interesting methods we can reuse to reach our need to check nullity of an object to throw an exception with or without a message, some methods are even now available to use in Java 8 as static predicates:

  • Objects::isNull
  • Objects::nonNull

Instead of our own custom check-up, here is how you can use it to be sure a parameter is always there:

Objects.requireNonNull(parameter, "Parameter must not be null");

Another method to just see if a parameter is null without throwing an exception:

boolean parameterNull = Objects.isNull(parameter);

Some others methods are ready to use like:

  • Objects.nonNull(Object object)
  • Objects.requiredNonNull(T obj, Supplier<String> messageSupplier)

Objects class quickly became popular and even used everywhere in the JDK source code, as on these functions of the Stream class and into many more others:

/**
* Returns an infinite sequential unordered stream where each element is
* ...
* @param <T> the type of stream elements
* @param s the {@code Supplier} of generated elements
* @return a new infinite sequential unordered {@code Stream}
*/
public static<T> Stream<T> generate(Supplier<T> s) {
Objects.requireNonNull(s);
return StreamSupport.stream(
new StreamSpliterators.InfiniteSupplyingSpliterator.OfRef<>(Long.MAX_VALUE, s), false);
}

/**
* Creates a lazily concatenated stream whose elements are all the
* elements of the first stream followed by all the elements of the
* ...
* @param <T> The type of stream elements
* @param a the first stream
* @param b the second stream
* @return the concatenation of the two input streams
*/
public static <T> Stream<T> concat(Stream<? extends T> a, Stream<? extends T> b) {
Objects.requireNonNull(a);
Objects.requireNonNull(b);

@SuppressWarnings("unchecked")
Spliterator<T> split = new Streams.ConcatSpliterator.OfRef<>(
(Spliterator<T>) a.spliterator(), (Spliterator<T>) b.spliterator());
Stream<T> stream = StreamSupport.stream(split, a.isParallel() || b.isParallel());
return stream.onClose(Streams.composedClose(a, b));
}

More details are available in the documentation.

A real live example

If you are building a little SDK and you want to set up the foundation of how your service will be built, here is an approach.

SDK Configuration:

/**
 * Just to illustrate/simulate the sdk
 * The configurations of our sdk go here
 */
public class SDKConfig {
    // Required
    private String key;
    // Required
    private String secret;
    // Optional, the default version will be used(2.0.4)
    private String version;
    
    public String getKey() {
        return key;
    }

    public SDKConfig key(String key) {
        this.key = key;
        return this;
    }

    public String getSecret() {
        return secret;
    }

    public SDKConfig secret(String secret) {
        this.secret = secret;
        return this;
    }

    public String getVersion() {
         return version;
    }

    public SDKConfig version(String version) {
        this.version = version;
        return this;
    }

    public SDK build() {
        return new SDK(this);
    }
}

SDK Entry Point:

/**
 * The sdk main component which requires the config to perform more actions
 */
public class SDK {
    private SDKConfig sdkConfig;
    public SDK(SDKConfig sdkConfig){
        Objects.requireNonNull(sdkConfig, "SDK config is null");
        Objects.requireNonNull(sdkConfig.getKey(), "The API key cannot be null");
        Objects.requireNonNull(sdkConfig.getSecret(), "The API secret cannot be null");

        this.sdkConfig = sdkConfig;
    }

    // Do whatever you want here ...
}

Use the SDK the right way:

// Let's initiate our SDK config
SDKConfig sdkConfig = new SDKConfig()
        .secret("my secret")
        .key("my key")
        .version("my version");
// We build our SDK component
SDK sdk = sdkConfig.build();

A test that show the wrong parameter case and immediately throwing an NPE:

@Test(expected = NullPointerException.class)
public void catchBadSDKConfig() {
// We instantiate an SDK with bad configs(no secret provided)
SDKConfig sdkConfig = new SDKConfig()
.key("my key")
.version("my version");

SDK sdk = sdkConfig.build();
}

Have such check can really help to build a solid base of our SDK with a clean and more concise line of codes. That also means avoiding explicitly throw NullPointerException aka NPE everywhere.

Note: I'm not telling it's the best approach, but a way that can guide you on your stuff.

Conclusion

To resume, in this article we have seen a clean and simple way to throw an exception on required parameters when needed.

The full source code is available over on GitHub.


Orleando Dassi

I'm a Solutions Architect who is constantly learning to better himself while impacting the community by producing technical articles and videos, what describes me the most is my flexibility.

Related Posts

Docker

Dockerize Spring Boot and MySQL with Docker Compose

Docker has revolutionized application deployment by enabling developers to package applications and their dependencies into portable containers. In this comprehensive guide, we'll explore how to dockerize a Spring Boot application with MySQL, leveraging the power Read more...

Java

Safely toString a Java object

In this little article, we will see how to get the string representation(tostring) of an object cautiously, that means avoiding NullPointerException. Getting the String representation of a Java object is something we often do for Read more...

Shares