【问题标题】:Java order of OR comparisonOR比较的Java顺序
【发布时间】:2011-06-21 13:38:35
【问题描述】:

当参数为空时,下面的 sn-p 是否会抛出 NPE?

public void doSomething(String string) {
    if (string.trim().equals("") || string==null) {
    [...]
    }
}

我在其他人的代码中发现了这一点(其他人应该比我更有经验)。由于我在处理这段代码时遇到了困难,我想问一下是否应该反转比较,或者 Java 编译器是否足够聪明,可以交换操作数。我无法直接控制这段代码,也不会因为许多 catch 块而引发 NPE。

谢谢

【问题讨论】:

  • java.sun.com/docs/books/jls/third_edition/html/… - evaluates its right-hand operand only if the value of its left-hand operand is false
  • 我们将它们(&&||)结合使用是什么?有执行顺序吗?还是还是从左到右的评价?
  • 你自己试试吧? 5行代码,你就知道答案了。
  • 参数名为str,但变量名为string。这是正确的吗?
  • @walkingTarget:我刚刚在@Martijn Courteaux 更正了我的答案后更正了这个问题。

标签: java nullpointerexception


【解决方案1】:

是的。当stringnull 时,该sn-p 代码将抛出NullPointerException。建议将其更改为以下内容:

public void doSomething(String string) {
    if (string==null || string.trim().equals("")) {
        // ...
    }
}

【讨论】:

  • 我可以随意将参数名称更改为string :D
  • @Martijn Courteaux:谢谢。我没有完全发现参数变量名与if 块中的变量名不同。我刚刚从问题中剪切/粘贴了它。看起来问题也是错误的,但我只是在那里更正了。
【解决方案2】:

它会抛出一个NullPointerException,因为如果string 为空并且你尝试修剪一个null,它会抛出异常。在尝试trim().之前先尝试进行空检查

【讨论】:

    【解决方案3】:

    是的,这对我来说看起来很狡猾。几乎可以肯定,它应该是相反的。 Java 逻辑运算符(如在 C 和 C++ 中)具有“短路”功能,即首先计算左侧操作数,然后仅在需要时才计算右侧操作数。

    [注意:您不能尝试运行它来确定它是否引发异常吗?]

    【讨论】:

    • 我无法在刚刚查看的代码中进行调试。想想看,你甚至得到了更多的代表:)
    • @djechelon:您可以简单地将这个 sn-p 复制并粘贴到一个小型测试程序中......!
    【解决方案4】:

    是的,每个明智的 IDE 都会抱怨这段代码,因为永远无法评估右半部分。

     if (string.trim().equals("") || string==null) {
    

    如果字符串为空,左边部分抛出 NPE,所以右边部分永远不会被评估

    【讨论】:

    • 可以评估右半部分。它永远不会被评估为true
    • @Atreys 我的意思是if (the string is null){ the left part throws a NPE, so the right part never gets evaluated } :-)
    • @atreys:无论正确表达的价值如何,如果我得到 NPE,就不需要再评估任何东西了,这很痛苦...... :)
    • 整个答案似乎不正确。我想不出我使用过的任何 Java IDE 会抱怨这一点,只是因为变量 - 可能 - 为空,因此 - 可能 - 抛出 NullPointerException 并且 - 可能 - 意味着右手边可以' t 被评估。而且,如果你仔细想想,这样做是完全荒谬的。
    • Eclipse 在 null 和非 null 情况下都不会打印任何警告。它只抱怨未初始化的变量,而不是空变量。
    【解决方案5】:

    尝试使用 if(!"".equals(someString)) 来避免显式空检查

    【讨论】:

    • 这不一样(修剪在哪里?),也不是问题的答案......
    • @Oli Charlesworth , @Asaph 包含 WhiteSpace Char(s) 的字符串在所有情况下对我来说都不是 isEmpty
    【解决方案6】:

    优先级相等的二元运算符总是从左到右进行计算,除了赋值(在我能想到的几乎所有语言中)这在这种情况下很重要,因为|| 是一个捷径运算符。如果结果已知,即第一个表达式为真,则不会计算第二个表达式。所以使用||&&来检查null的正确方法如下。

    if(text == null || text.method())
    

    if(text != null && text.method2())
    

    顺序是这样的,因为我们用英语从左到右(和从上到下)阅读。参考文献在日语中,您从上到下然后从右到左阅读。

    【讨论】:

    • 这不是优先级/关联性问题。在 C/C++/Java(和其他一些)中,逻辑运算符具有“短路”功能。
    • 对我来说重要的问题是左表达式在右表达式之前被评估。如果首先评估权利,则 OP 的代码将使用捷径。
    • 实际上,短路意味着当第一个操作数足够时,不会评估第二个操作数。这对于避免拆分空检查和模式检查至关重要,因为如果空检查通过,则不会评估另一个操作数并且不会进入 NPE
    • 短路仅意味着当结果已知时,并非所有子表达式都被计算。在逻辑编程语言中,任何已知的子表达式都可能意味着不计算其他表达式。
    • @Peter:是的,但是在 Java(和 C 等)中,标准中有一个特定的点指出左操作数总是被评估,并且仅在必要时评估右侧操作数。这就是这里的重点……
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-01-05
    • 1970-01-01
    • 2010-09-11
    • 2021-07-08
    • 2020-01-19
    相关资源
    最近更新 更多