Why should one use Objects.requireNonNull()?
Because you can make things explicit by doing so. Like:
public class Foo {
private final Bar bar;
public Foo(Bar bar) {
Objects.requireNonNull(bar, "bar must not be null");
this.bar = bar;
}
Or shorter:
this.bar = Objects.requireNonNull(bar, "bar must not be null");
Now you know:
- when a Foo object was successfully created using
new()
- then its bar field is guaranteed be non-null.
Compare that to: you create a Foo object today, and tomorrow you invoke a method that uses that field and throws. Most likely, you will not know tomorrow why that reference was null yesterday when it got passed to the constructor!
In other words: by explicitly using this method to check incoming references you can control the point in time when the exception will be thrown. And most of the time, you want to fail as fast as possible!
The major advantages are:
- as said, controlled behavior
- easier debugging - because you throw up in the context of the object creation. At a point in time where you have a certain chance that your logs/traces tell you what went wrong!
- and as shown above: the true power of this idea unfolds in conjunction with final fields. Because now any other code in your class can safely assume that
bar
isn't null - and thus you do not need anyif (bar == null)
checks in other places!
But NullPointerException will be thrown anyway if a null object is dereferenced. So, why should one do this extra null check and throw NullPointerException?
It means you detect the problem immediately and reliably.
Consider:
- The reference may not be used until later in the method, after your code has already performed some side-effects
- The reference may not be dereferenced in this method at all
- It could be passed to completely different code (i.e. cause and error are far apart in code space)
- It could be used much later (i.e. cause and error are far apart in time)
- It may be used somewhere that a null reference is valid, but has an unintended effect
.NET makes this better by separating NullReferenceException
("you dereferenced a null value") from ArgumentNullException
("you shouldn't have passed in null as an argument - and it was for this parameter). I wish Java did the same thing, but even with just a NullPointerException
, it's still much easier to fix code if the error is thrown at the earliest point at which it can be detected.
Fail-fast
The code should crash as soon as possible. It should not do half of the work, dereference the null and only then crash, leaving half of some work done causing the system to be in an invalid state.
This is commonly called "fail early" or "fail-fast".