Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/372.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 什么';番石榴的要点是什么_Java_Null_Guava_Preconditions - Fatal编程技术网

Java 什么';番石榴的要点是什么

Java 什么';番石榴的要点是什么,java,null,guava,preconditions,Java,Null,Guava,Preconditions,我对番石榴很陌生(老实说,我不是“很新”,我是这方面的新手),所以我决定浏览一些文档,读到这篇文章时感到非常惊讶: 我不明白这种方法的意义。 这意味着,与其做: myObject.getAnything(); (如果myObject为null,则可能导致NullPointerException) 我应该用 checkNotNull(myObject).getAnything(); 如果myObject为null,则将抛出NullPointerException,如果不为null,则返回my

我对番石榴很陌生(老实说,我不是“很新”,我是这方面的新手),所以我决定浏览一些文档,读到这篇文章时感到非常惊讶:

我不明白这种方法的意义。 这意味着,与其做:

myObject.getAnything();
(如果myObject为null,则可能导致
NullPointerException

我应该用

checkNotNull(myObject).getAnything();
如果
myObject
为null,则将抛出
NullPointerException
,如果不为null,则返回
myObject

我很困惑,这可能是有史以来最愚蠢的问题,但是

这有什么意义? 考虑到我能想到的任何情况,这两条线的作用与结果完全相同

我甚至不认为后者更具可读性

所以我肯定错过了什么。这是什么

myObject.getAnything()(如果myObject为null,则可能导致NullPointerException)

不。。。只要
myObject==null
,它就会抛出NPE。在Java中,使用
null
receiver调用方法是不可能的(理论上的例外是静态方法,但它们可以而且应该总是在没有任何对象的情况下调用)


我应该使用
checkNotNull(myObject).getAnything()

不,你不应该。这将是相当多余的(更新

您应该使用
checkNotNull
以快速失败。没有它,您可能会将非法的
null
传递给另一个方法,该方法会进一步传递它,以此类推,最终失败。然后您可能需要一些运气来发现第一个方法实际上应该拒绝
null


yshavit的答案提到了一个重要的点:传递非法值是不好的,但是存储它并在以后传递它更糟糕

更新 其实

 checkNotNull(myObject).getAnything()
这也是有道理的,因为您清楚地表达了不接受任何空值的意图。如果没有它,有人可能会认为你忘记了支票,并将其转换为

 myObject != null ? myObject.getAnything() : somethingElse
奥托,我认为这张支票不值得这么冗长。在A型系统中,考虑了可空性,并给出了一些类似于

的语义糖。
 myObject!!.getAnything()                    // checkNotNull
 myObject?.getAnything()                     // safe call else null
 myObject?.getAnything() ?: somethingElse    // safe call else somethingElse

对于可为null的
myObject
,而标准的点语法仅在
myObject
已知为非null时才允许使用。

其思想是快速失败。例如,考虑这个愚蠢的类:

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

相反,想象一下这个构造函数:

public Foo(String s) {
    this.s = checkNotNull(s);
}
现在,如果有人在其中放入一个
null
,您将立即发现——堆栈跟踪将准确地指向出错的调用


另一个有用的方法是,如果您想在执行可修改状态的操作之前检查参数,则可以使用该方法。例如,考虑这个类,计算它得到的所有字符串长度的平均值:

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;
    }
}
调用
accept(null)
将导致抛出NPE——但不是在
stringsSeen
增加之前。这可能不是你想要的;作为该类的用户,我可能希望如果它不接受null,那么如果传递null,它的状态应该保持不变(换句话说:调用应该失败,但不应该使对象无效)。显然,在本例中,您还可以通过在递增
stringsSeen
之前获取
s.length()
来修复此问题,但您可以看到,对于更长更复杂的方法,首先检查所有参数是否有效,然后才修改状态可能很有用:

    public void accept(String s) {
        checkNotNull(s); // that is, s != null is a precondition of the method

        stringsSeen++;
        totalLengthSeen += s.length();
    }

几分钟前,我已经读了这整篇文章。尽管如此,我还是感到困惑,为什么我们应该使用
checkNotNull
。然后看看番石榴,我得到了我所期望的。过度使用
checkNotNull
肯定会降低性能

我的想法是,
checkNotNull
方法值得用于数据验证,该验证直接来自用户或终端API到用户的交互。它不应该在内部API的每个方法中都使用,因为使用它您不能停止异常,而应该纠正您的内部API以避免异常

根据文件:

使用checkNotNull:

性能警告

这个类的目标是提高代码的可读性,但在某些情况下 在这种情况下,可能会付出巨大的性能成本。 请记住,消息构造的参数值必须全部为 急切地计算,可能会创建自动装箱和varargs数组 同样,即使先决条件检查成功(应该如此) 几乎总是在生产中进行)。在某些情况下,这些都是浪费 CPU周期和分配加起来就是一个真正的问题。 性能敏感的前提条件检查始终可以转换为 习惯形式:

if(值<0.0){
抛出新的IllegalArgumentException(“负值:”+值);
}

这就像在方法的开头检查该方法的前提条件是否有效一样?准确地说。立即检查非法论点可以确保你以后不必追查它们。此外,每个查看该方法的人都会看到什么是禁止的(当然,它应该被记录在案…。@Juru:是的,这就是为什么它在
预条件类中的原因!它不应该更像这个.s=premissions.checkNotNull(s);但是是的,我没有想到储藏箱,打字机
public static double sqrt(double value) {
     Preconditions.checkArgument(value >= 0.0, "negative value: %s", value);
     // calculate the square root
}
if (value < 0.0) {
     throw new IllegalArgumentException("negative value: " + value);
}