【问题标题】:Java short circuit evaluationJava短路评估
【发布时间】:2010-12-21 11:12:45
【问题描述】:

我以为Java有短路评估,但这一行仍然抛出空指针异常:

if( (perfectAgent != null) && (perfectAgent.getAddress().equals(entry.getKey())) ) {

在这种情况下,perfectAgentnull,所以我只想让整个表达式返回 false,但我的应用程序仍然在这条线上崩溃并出现 NullPointerException。

编辑,一般回应:

由于perfectAgentnull,因此&& 右侧的任何内容都不应执行,因为表达式不可能为真。更重要的是,不可能执行perfectAgent.getAddress(),因为perfectAgent 不包含有效的引用(它为空且全部为空)。我正在尝试使用短路评估来不必在单独的语句中检查 null,因为这会使逻辑更加草率。

编辑 2(或者,我是个白痴): 是的,就像生活中的许多事情一样,在向全世界宣布自己是个白痴之后,您就会立即找到答案。在这种情况下,我在执行其他操作时关闭了 Eclipse 的自动构建并且没有重新打开它,所以我正在调试与我的源代码不匹配的类文件。

【问题讨论】:

  • 您是否检查过该条目不为空?
  • perfectAgent.getAddress() 是否有可能返回 null?
  • 你确定 getAddress() 没有返回 null 吗?
  • 您不是在针对较新的源(具有不同的行号)在旧 jar 中调试代码,是吗?我最近被那个咬了……
  • +1 公开说出问题所在,即使这有点尴尬。

标签: java logical-operators short-circuiting


【解决方案1】:

您确保perfectAgent 不为空,因此perfectAgent.getAddress()entryentry.getKey() 中的一个或多个必须为空。或者 getAddress() 或 getKey() 在他们的实现中遇到了 NPE。

要调试这类事情,首先查看堆栈跟踪以确定位置。这将告诉您它是否发生在 getAddress() 或 getKey() 或调用它们的粘贴代码 sn-p 中。接下来,如果它在这个sn-p中,在if之前添加一些代码来测试哪个为null。您可以使用旧的 System.err.println() 或 assertions。 (如果您使用断言,请务必使用 java 命令的 -enableassertions 标志启用它们。)

更新:所以我的解释被证明是错误的......问题提出了两个相互矛盾的事实(这条线路上有一个 NPE,但应该发生短路),我自动假设第一个事实是正确的,而第二个事实是错误的,而实际上这是一个完全不同的问题,完全是由于关闭了 Eclipse 中的自动构建。呸!在调试“不可能”的事情时,从根本上持怀疑态度会有所帮助。

【讨论】:

    【解决方案2】:

    如果 perfectAgent 确实为 null,那么该代码 不会 抛出异常(至少假设没有奇怪的线程处理发生,将其从非 null 更改为 null 中途通过表达式)。如果你能制作一个简短但完整的程序来演示它,我会非常震惊。

    所以是的,你的直觉是正确的 - 这应该不是问题。在别处寻找原因。我强烈怀疑perfectAgent 不是实际上为空,并且您在该代码中遇到了可能导致异常的任何其他情况。

    我建议您尝试将那段代码提取成一个简短但完整的示例 - 如果您可以这样做,我会吃掉我的隐喻帽子;如果没有,您希望在尝试提取时发现问题。

    是什么让您认为perfectAgent 真的 null?尝试在它之前插入此代码:

    if (perfectAgent == null)
    {
        System.out.println("Yup, it's null");
    }
    

    另一个非常非常渺茫的可能性是您遇到了 JIT 错误 - 但我非常怀疑。

    【讨论】:

    • 哦,是的,我不认为这是一个 JIT 错误,只是想弄清楚我做错了什么。
    • 您在显示的代码中没有做错任何事情 - 至少没有什么会导致这种情况。我怀疑是什么让你相信 perfectAgent 为空:)
    • 查看我的 Edit2。就在鼻子上。
    • @Jim:如果perfectAgent 真的为空,那么由于短路,除了空比较(在显示的代码之外)之外不会执行任何操作。是的,下一行代码可能会抛出 NPE - 但显示的代码不会。
    • 乔恩,我是个白痴,对不起!当我读/写这篇文章时,我的孩子们正在回学校。我会反转。
    【解决方案3】:

    高级调试课程 #1:

    如果您遇到看似不可能的错误(例如,与您对 Java 的了解相矛盾的错误),请执行以下操作:

    • 请查阅信誉良好的教科书(或者更好的是相关标准),以确认您的理解没有缺陷。 (在这种情况下,你的理解是正确的,任何一本像样的教科书都会在一分钟内证实这一点。)

    • 检查所有可能导致不可能错误的愚蠢事情。诸如不保存文件、不进行完整构建、运行旧/陈旧版本的应用程序、位于错误的目录等等。

    总之,学会多怀疑自己。

    【讨论】:

      【解决方案4】:

      尝试像这样格式化您的代码:

      if( 
        (perfectAgent != null) 
        && (
            perfectAgent.getAddress()
            .equals(
             entry.getKey()
            )
           ) 
        ) {
      

      它应该为您提供更好的堆栈跟踪行条目。

      【讨论】:

        【解决方案5】:

        大谜团。我复制了您的代码行并使用perfectAgent == nullentry == nullentry.getKey() == null 以及它们的组合进行了测试:我的测试台中没有 NPE(Java 1.6)。

        无论它是什么烦人的错误,我怀疑它与短路评估有关。如果是这条线导致 NPE,据我所知,perfectAgent 不为空。祝你好运 - 一旦你发现它,就向我们展示它:)

        【讨论】:

          【解决方案6】:

          Java 确实有短路评估。也许entrynull,所以entry.getKey() 导致NullPointerException。另一种可能性是getAddress() 要么返回null,要么在某处发生NullPointerException(如果它比简单的return 语句更复杂)。

          编辑:我在您声明的地方看到了您的编辑:

          更重要的是,不可能执行perfectAgent.getAddress() ...

          但是如果perfectAgent.getAddress()成功执行并且返回null怎么办?明白我的意思...

          【讨论】:

            【解决方案7】:

            除了 perfectAgent 之外还有三个引用可以为空:

            • perfectAgent.getAddress()
            • 条目
            • entry.getKey()

            分解语句或在调试器中运行它。

            【讨论】:

            • entry.getKey() 为 null 不会导致 OP 的代码 sn-p 中出现 NullPointerException
            • Object.equals(null) 总是返回 false。所以它不会是 entry.getKey() 返回 null。所以它必须是列出的前两个之一。
            • 啊,是的,你们都说得对。只有前两个是候选人。
            猜你喜欢
            • 1970-01-01
            • 2015-11-14
            • 2017-01-21
            • 2012-02-10
            • 1970-01-01
            • 2013-05-21
            • 2021-11-21
            • 2016-11-26
            • 2019-05-12
            相关资源
            最近更新 更多