番石榴checkNotNull有什么意义 [英] What's the point of Guava checkNotNull
问题描述
我是Guava的新手(说实话,我不是非常新的,我是这个主题的完整新手)所以我决定通过一些文档并在阅读本文时非常惊讶:
I'm pretty new to Guava (let's be honest, I'm not "pretty new", I'm a complete rookie on that subject) and so I decided to go through some documentation and got quite amazed while reading this:
com.google.common.base.Preconditions.checkNotNull(...)
我不明白这个方法的意义。
这意味着代替:
I don't get the point of this method. This means that instead of doing :
myObject.getAnything();
(这可能导致 NullPointerException
如果myObject为null)
(which might cause a NullPointerException
if myObject is null)
我应该使用
checkNotNull(myObject).getAnything();
将抛出 NullPointerException
if myObject
为null并返回 myObject
如果它不为null。
which will throw a NullPointerException
if myObject
is null and return myObject
if it is not null.
我很困惑,这可能是有史以来最愚蠢的问题但是......
I'm puzzled and this might be the stupidest question ever but ...
这有什么意义呢?
这两行与我能想到的任何情况完全相同。
What is the point of this? Those two lines do the exact same thing as for outcomes given any situations I can think of.
我甚至认为后者更具可读性。
I don't even think that the latter is more readable.
所以我必须遗漏一些东西。它是什么?
So I must be missing something. What is it?
推荐答案
想法是快速失败。例如,考虑这个愚蠢的类:
The idea is to fail fast. For instance, consider this silly class:
public class Foo {
private final String s;
public Foo(String s) {
this.s = s;
}
public int getStringLength() {
return s.length();
}
}
假设你不想允许空值对于 s
。 (否则 getStringLength
将抛出NPE)。随着类的原样,当你捕获 null
时,已经太晚了 - 很难找到谁把它放在那里。罪魁祸首很可能是一个完全不同的类,而且很久以前就已经构建了 Foo
实例。现在你必须梳理你的代码库,找出谁可能在那里放一个 null
值。
Let's say you don't want to allow null values for s
. (or else getStringLength
will throw a NPE). With the class as-is, by the time you catch that null
, it's too late -- it's very hard to find out who put it there. The culprit could well be in a totally different class, and that Foo
instance could have been constructed a long time ago. Now you have to comb over your code base to find out who could possibly have put a null
value there.
相反,想象一下这个构造函数:
Instead, imagine this constructor:
public Foo(String s) {
this.s = checkNotNull(s);
}
现在,如果有人提出 null
在那里,你会立即找到 - 你将拥有堆栈跟踪指向你错误的电话。
Now, if someone puts a null
in there, you'll find out right away -- and you'll have the stack trace pointing you exactly to the call that went wrong.
另一个有用的方法是,如果要在执行可以修改状态的操作之前检查参数。例如,考虑这个类计算它获得的所有字符串长度的平均值:
Another time this can be useful is if you want to check the arguments before you take actions that can modify state. For instance, consider this class that computes the average of all string lengths it gets:
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;
}
}
调用接受(null)
会导致NPE被抛出 - 但是在 stringsSeen
之前不会增加。这可能不是你想要的;作为类的用户,我可能期望如果它不接受空值,那么如果传递null,它的状态应该保持不变(换句话说:调用应该失败,但它不应该使对象无效)。显然,在这个例子中,您还可以通过在递增 stringsSeen
之前获取 s.length()
来修复它,但是你可以看看如何使用更长且更复杂的方法,首先检查所有参数是否有效,然后只修改状态可能很有用:
Calling accept(null)
will cause an NPE to get thrown -- but not before stringsSeen
has been incremented. This may not be what you want; as a user of the class, I may expect that if it doesn't accept nulls, then its state should be unchanged if you pass a null (in other words: the call should fail, but it shouldn't invalidate the object). Obviously, in this example you could also fix it by getting s.length()
before incrementing stringsSeen
, but you can see how for a longer and more involved method, it might be useful to first check that all of your arguments are valid, and only then modify state:
public void accept(String s) {
checkNotNull(s); // that is, s != null is a precondition of the method
stringsSeen++;
totalLengthSeen += s.length();
}
这篇关于番石榴checkNotNull有什么意义的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!