What is the meaning of guava checkNotNull

I am new to Guava (to be honest, I am not “fairly new”, I am a complete newbie to this issue) and therefore I decided to read some documents and am very amazed when reading this

com.google.common.base.Preconditions.checkNotNull(...)

I do not understand the meaning of this method. This means that instead of executing:

 myObject.getAnything(); 

(which could lead to a NullPointerException if myObject is null)

I have to use

 checkNotNull(myObject).getAnything(); 

which will throw a NullPointerException if myObject is null and returns myObject if it is not null.

I am puzzled, and this may be the dumbest question, but ...

What is the meaning of this? These two lines do the same as for the results, given any situations that I can think of.

I don’t even think that the latter is more readable.

So I have to miss something. What is it?

+44
java null guava preconditions
03 Oct '14 at 18:05
source share
3 answers

The idea is to fail quickly. For example, consider this silly class:

 public class Foo { private final String s; public Foo(String s) { this.s = s; } public int getStringLength() { return s.length(); } } 

Say you do not want to allow null values ​​for s . (otherwise getStringLength will throw an NPE). With the as-is class, by the time you realize that null is too late, it is very difficult to figure out who put it there. The culprit could well have been in a completely different class, and that the Foo example could have been built a long time ago. Now you need to comb your code base to find out who could put the null value there.

Imagine this constructor instead:

 public Foo(String s) { this.s = checkNotNull(s); } 

Now, if someone puts null there, you will know right away - and you will have a stack trace indicating that you really made a mistake.




Another time, this can be useful if you want to check the arguments before taking actions that can change state. For example, consider this class, which calculates the average of all the lengths of the strings it receives:

 public class StringLengthAverager { private int stringsSeen; private int totalLengthSeen; public void accept(String s) { stringsSeen++; totalLengthSeen += s.length(); } public double getAverageLength() { return ((double)totalLengthSeen) / stringsSeen; } } 

Calling accept(null) will cause the NPE to be reset - but not before the stringsSeen been incremented. Perhaps this is not what you want; as a user of the class, I can expect that if it does not accept NULL values, then its state should not change if you pass zero (in other words: the call should fail, but it should not deprive the object). Obviously, in this example, you can also fix this by getting s.length() before increasing stringsSeen , but you can see how, for a longer and more complex method, it may be useful to first verify that all your arguments are valid, and only then change state:

  public void accept(String s) { checkNotNull(s); // that is, s != null is a precondition of the method stringsSeen++; totalLengthSeen += s.length(); } 
+74
Oct 03 '14 at 18:16
source share

myObject.getAnything(); (which may throw a NullPointerException if myObject is null)

No ... it will throw an NPE whenever myObject == null . In Java, there is no way to call a method with a null receiver (a theoretical exception is static methods, but they can and should always be called without any object).




I have to use checkNotNull(myObject).getAnything();

No, not worth it. This will be pretty redundant ( Update ).

You must use checkNotNull for a quick crash. Without this, you can pass illegal null another method that passes it on, etc. Etc. Where he finally fails. Then you may need luck to find out that actually the first method was supposed to reject null .




Yshavit's answer points to an important point: transmitting an illegal value is bad, but saving it and passing it on later is even worse.

Update

In fact,

  checkNotNull(myObject).getAnything() 

makes sense since you are clearly expressing your intention not to accept any meanings. Without this, someone might think that you forgot the check and turned it into something like

  myObject != null ? myObject.getAnything() : somethingElse 

OTOH, I don’t think checking is worth the word. In a better language , the type system will consider the value of nullability and give us some semantic sugar, for example

  myObject!!.getAnything() // checkNotNull myObject?.getAnything() // safe call else null myObject?.getAnything() ?: somethingElse // safe call else somethingElse 

for nullable myObject , while the standard point syntax will only be allowed when myObject is not known to be null.

+5
Oct 03 '14 at 18:14
source share

I read this entire thread a few minutes ago. However, I was confused why we should use checkNotNull . Then look at the Precondition class document from Guava, and I got what I expected. Excessive use of checkNotNull will degrade performance.

It seems to me that the checkNotNull method checkNotNull needed to verify data that comes from the user directly or the very end of the API for interacting with the user. It should not be used in all methods of the internal API, because using it you cannot stop the exception, rather correct your internal API to avoid the exception.

According to DOC: Link

Using checkNotNull:

 public static double sqrt(double value) { Preconditions.checkArgument(value >= 0.0, "negative value: %s", value); // calculate the square root } 

Performance warning

The goal of this class is to improve the readability of the code, but in some circumstances it can have significant execution cost. Remember that the parameter values ​​for building messages should be calculated impatiently, and the creation of autoboxing and the varargs array can also occur even when the precondition check is then performed (as it should almost always be in production). In some cases, these losses. Process cycles and allocations can pose a real problem. Performance-sensitive precondition checks can always be converted to the usual form:

 if (value < 0.0) { throw new IllegalArgumentException("negative value: " + value); } 
+1
Mar 06 '17 at 17:05
source share



All Articles