当前位置: 首页 > 知识库问答 >
问题:

番石榴checkNotNull[duplicate]有什么用

孟乐逸
2023-03-14

我对番石榴很陌生(说实话,我不是“很新”,我是这个主题的新手),所以我决定浏览一些文档,在阅读本文时感到非常惊讶:

com.谷歌.common.base.前提条件.checknotnull(...)

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

myObject.getAnything();

(如果myObject为null,这可能会导致NullPointerException

我应该用

checkNotNull(myObject).getAnything();

如果我的对象为空,这将抛出一个空点例外,如果它不是空,则返回我的对象

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

这有什么意义?这两条线和我能想到的任何情况下的结果是完全一样的。

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

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

共有3个答案

壤驷高洁
2023-03-14

我几分钟前就读过整个帖子。尽管如此,我还是很困惑,为什么我们应该使用检查不取消。然后查看番石榴的先决条件类文档,我得到了我所期望的。过度使用检查不取消肯定会降低性能。

我的想法是checkNotNull方法对于来自用户直接或非常端的应用编程接口到用户交互的数据验证是值得需要的。它不应该在内部应用编程接口的每一个方法中使用,因为使用它你不能停止异常,而是纠正你的内部应用编程接口以避免异常。

根据文档:链接

使用检查不取消:

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

关于性能的警告

此类的目标是提高代码的可读性,但在某些情况下,这可能会导致显著的性能损失。请记住,必须立即计算消息构造的所有参数值,也可能会创建自动装箱和varargs数组,即使先决条件检查随后成功(在生产中几乎总是如此)。在某些情况下,这些浪费的CPU周期和分配可能会增加一个实际问题。性能敏感的前提条件检查始终可以转换为常规形式:

if (value < 0.0) {
     throw new IllegalArgumentException("negative value: " + value);
}
嵇浩然
2023-03-14

myObject。获取任何东西()(如果myObject为null,可能会导致NullPointerException)

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

我应该使用< code>checkNotNull(myObject)。getAnything();

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

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

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

实际上,

 checkNotNull(myObject).getAnything()

这也很有道理,因为你清楚地表达了不接受任何空话的意图。如果没有它,有人可能会认为你忘记了支票并将其转换为类似的东西

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

奥托,我不认为这张支票值得这么多废话。在更好的语言中,类型系统会考虑可空性,并给我们一些语义上的好处,如

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

对于可空的< code>myObject,只有当< code>myObject已知为非空时,才允许使用标准的点语法。

西门品
2023-03-14

我们的想法是快速失败。例如,考虑一下这个愚蠢的类:

public class Foo {
    private final String s;

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

    public int getStringLength() {
        return s.length();
    }
}

假设您不想允许 s 的空值。(否则获得字符串长度将抛出一个 NPE)。按原样使用类时,当你捕获该空值时,为时已晚 - 很难找出谁把它放在那里。罪魁祸首很可能在一个完全不同的类中,而Foo实例可能是很久以前构建的。现在,您必须梳理您的代码库,以找出谁可能在那里放置了一个空值。

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

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;
    }
}

调用< code>accept(null)将导致抛出NPE——但不会在< code > string seen 递增之前。这可能不是你想要的;作为该类的用户,我可能认为如果它不接受空值,那么如果您传递一个空值,它的状态应该是不变的(换句话说:调用应该失败,但不应该使对象无效)。显然,在本例中,您还可以通过在递增< code>stringsSeen之前获取< code>s.length()来修复它,但是您可以看到,对于一个更长、更复杂的方法,首先检查所有参数是否有效,然后才修改状态可能是有用的:

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

        stringsSeen++;
        totalLengthSeen += s.length();
    }
 类似资料:
  • 问题内容: 我是番石榴的新手(老实说,我不是“新手”,我是这个主题的新手),所以我决定阅读一些文档,并在阅读本文时感到非常惊讶: 我不明白这种方法的意义。这意味着不要这样做: (如果myObject为null ,则可能会导致) 我应该用 这 将 抛出如果是空和返回,如果它不为空。 我很困惑,这可能是有史以来最愚蠢的问题,但是… 这有什么意义呢?在我能想到的任何情况下,这两行所做的事情与结果完全一样

  • 问题内容: 有没有理由 但不是 ? 如何正确过滤列表?我可以用 当然可以,但是如果我理解正确的话,就不能保证我的订购顺序保持不变。 问题答案: 它之所以未实现,是因为它会在返回的List视图上暴露大量危险的慢速方法,例如#get(index)(会引发性能错误)。ListIterator也很难实现(尽管我几年前提交了一个补丁来解决)。 由于索引方法在过滤后的列表视图中效率不高,因此最好使用不包含它们

  • 问题内容: 刚刚发现了Guava库项目。 这些与GWT兼容吗? 问题答案: 从该页面的介绍性PDF中, 您可以在…上使用这些库。 在JDK 6上 在Android上, 我们认为。需要志愿者来帮助我们进行测试。 在Google App Engine上, 我们认为。需要志愿者来帮助我们进行测试。 在GWT上-参差不齐! 由于GWT的JDK库支持 可能参差不齐,也许是2/3,所以到目前为止,这些库中的东

  • 问题内容: 我想知道哪个更有效,为什么? 1) 要么 2) 问题答案: 我看不出您为什么要在此处使用builder的任何原因: 比在这种情况下制作一个更具可读性, 不会推断通用类型,并且在用作单行代码时必须自己指定类型, (来自docs) 在与另一个不可变集合调用时 做得很好( 尝试避免在安全的情况下实际复制数据 ), (从源) 调用以前创建的,同时避免为零元素和一元素集合创建任何列表(分别返回空

  • 我想为番石榴设个坑(http://pitest.org/)进行突变熟练度测试,但我在尝试运行时出现以下错误。这是我得到的错误: 基本上,要么PIT没有检测到测试,要么测试在PIT中运行不正常,所有测试都失败了。我读了这篇文章:JUnit测试通过,但PIT说套件不是绿色的,我认为“您的代码库是否包含可变静态状态?(例如在单例中)”是问题所在,但我不知道如何修复它。如果测试套件有一些隐藏的顺序依赖关系

  • 我的 Spark 版本是 2.2.0,它在本地工作,但在具有相同版本的 EMR 上,它给出了以下异常。