【问题标题】:Java Logical 'AND' vs 'OR' Short-Circuiting Consistency [duplicate]Java逻辑“与”与“或”短路一致性[重复]
【发布时间】:2012-11-05 17:35:26
【问题描述】:

可能重复:
Difference in & and &&

我已经阅读了几个关于 java 中短路操作的教程和答案,但我仍然不太了解 java 如何处理双垂直管道与双 & 符号的短路的区别。比如……

为什么逻辑与短路评估失败?

引用 JSL 15.23。条件与运算符 &&

The conditional-and operator && is like & (§15.22.2), but evaluates its right-hand operand only if the value of its left-hand operand is true.

public static void main( String... args ) {


    int a = 1;

    int b = 2;

    // Okay. Prints
    if( a == 1 | b == 3 ) {

        System.out.println( "Comparison via |" + "\na is " + a + "\nb is " + b );

    }

    // Okay. Prints
    if( a == 1 || b == 3 ) {

        System.out.println( "Comparison via ||" + "\na is " + a + "\nb is " + b );

    }

    // Okay. Does not print
    if( a == 1 & b == 3 ) {

        System.out.println( "Comparison via &" + "\na is " + a + "\nb is " + b );

    }

    // I don't understand. Shouldn't the Short Circuit succeed since the left side of the equation equals 1?
    if( a == 1 && b == 3 ) {

        System.out.println( "Comparison via &&" + "\na is " + a + "\nb is " + b );

    }

}

【问题讨论】:

  • |& 是按位或/和运算符;它们不同于 ||&&,它们是逻辑或/和运算符。
  • 我知道我没有得到第四名……我迷路了:-)
  • @NullUserException:嗯,它们在短路方面是不同的——但 JLS 定义了另一个......看我的回答。 (请注意,对于 boolean 操作数,它们仍然是逻辑运算符...)
  • @NullUserException |& 也是非短路逻辑或和和运算符。
  • 为了让短路在 #4 中起作用,它必须使 a==1 测试失败。在这种情况下,它可以断定 && 的结果是假的,因为 false&&anything 是假的。在测试 2 中发生短路,但这不会改变结果。

标签: java evaluation logical-operators


【解决方案1】:

我不明白。因为等式左边等于 1,所以短路不应该成功吗?

不,绝对不是。 && 的重点是,如果左边右边的操作数是true,结果只有true;短路意味着如果左操作数是false,则不会计算右操作数,因为此时答案是已知的。

您应该阅读 JLS 的 15.2315.24 部分了解更多详情:

条件与运算符 && 类似于 &(第 15.22.2 节),但仅当其左侧操作数的值为 true 时才计算其右侧操作数。

条件或运算符 ||运算符就像 | (§15.22.2),但仅当其左侧操作数的值为 false 时才评估其右侧操作数。

【讨论】:

  • 谢谢...知道了...有区别...我必须练习以使其“具体”:-)
【解决方案2】:

当与booleans 一起使用时,位运算符(|&)与逻辑运算符(||&&相似,除了: p>

  • && 的情况下,如果第一个参数是false,则第二个参数不会被计算,因为整个 表达式必须是false。对于&,两个参数都会被求值。

  • || 的情况下,如果第一个参数是true,则第二个参数不计算,因为整个 表达式必须是true。对于|,两个参数都会被计算。

这就是我们所说的“短路”:不计算第二个参数的过程,因为在某些情况下,我们可以仅从第一个参数的值知道 整个 表达式的值论据。


现在你问为什么下面的表达式是falsea == 1 &amp;&amp; b == 3。好吧,短路与它无关。 a = 1b = 2,所以声明 "a is 1 <b><i>and</i></b> b is 2 显然是 false,因为 b 不是 2

【讨论】:

  • tl;dr:按位(|&amp;)运算符对两个参数进行评估;逻辑运算符(||&amp;&amp;可以(但不总是)短路。
  • @NullUserException 他们什么时候不短路?
  • 在 OP 的例子中它没有短路。
  • @NullUserException 当然是的,因为a == 1true - 只要逻辑运算符可以短路,它们就会短路。
  • @NullUserException 我误解了,以为您在暗示某些情况下逻辑运算符即使可以短路也不会短路-我的错误。不管怎样,很高兴我们终于达成了一致!
【解决方案3】:

& 和 && 都要求双方都为真,因此代码的行为符合预期。

唯一的区别是 & 两边都执行,而 && 如果为 false 则只执行第一个,因为右边与最终结果无关。

这样的效果对于像这样的代码很重要

if (obj == null || obj.isSomthing())

如果你使用 | 会抛出 NPE并且 obj 为空。

【讨论】:

  • 这是一条滑溜溜的鱼... ;-)
  • 在将变量更改为布尔值后,这变得非常清晰:-)
【解决方案4】:

如果在计算第一个操作数后确定结果,则逻辑运算符 ||&amp;&amp; 会短路。对于||,如果第一个操作数的计算结果为true,则为&amp;&amp;,如果它的计算结果为false

如果|| 的第一个操作数是false,如果第二个操作数是true,它仍然可以产生true 的整体结果。同样,如果&amp;&amp; 的第一个操作数是true,如果第二个操作数是false,它仍然可以计算为false

在 Java 中,运算符 |&amp; 不仅是位运算符(当应用于整数参数时),而且是非短路逻辑运算符,无论第一个操作数的值如何,它们都会计算两个操作数。

【讨论】:

    【解决方案5】:
    if( a == 1 && b == 3 ) {
       System.out.println( "Comparison via &&" + "\na is " + a + "\nb is " + b );
    }
    

    首先它检查a == 1是否为真,所以它必须继续检查b == 3是否为真,所以true &amp;&amp; falsefalse,你没有得到输出。

    如果你有

    if( b == 3 && a == 1 ) {
           System.out.println( "Comparison via &&" + "\na is " + a + "\nb is " + b );
    }
    

    它会首先检查b == 3 是否是这样,因为不是这样,所以甚至不必费心查看a == 1,因为false &amp;&amp; whatever 始终是false,不管whatever 是什么。

    这能回答你的问题吗?

    【讨论】:

      猜你喜欢
      • 2016-08-24
      • 1970-01-01
      • 2012-02-04
      • 2010-12-18
      • 1970-01-01
      • 2021-05-08
      相关资源
      最近更新 更多