Java逻辑运算符中的“AND”和“OR”的短路一致性问题

4

可能重复:
& 和 && 的区别

我已经阅读了几篇关于Java中短路运算的教程和答案,但我仍然不太理解Java如何处理双竖线和双和号的短路。例如...

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

引用JSL 15.23. 条件-与运算符 &&

条件-与运算符 && 类似于 & (§15.22.2),但仅在其左操作数的值为 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 );

    }

}

3
“|”和“&”是位运算符,它们与逻辑或/与运算符“||”和“&&”不同。 - NullUserException
我知道我不明白第四个数字...我在那里迷失了 :-) - Edward J Beckett
@NullUserException:嗯,它们在短路方面是不同的 - 但是JLS根据另一个定义了一个...请看我的答案。(请注意,对于布尔操作数,它们仍然是逻辑运算符...) - Jon Skeet
@NullUserException |&也是非短路逻辑或和与运算符。 - Steve Kuo
为了使短路在#4中起作用,它必须失败a==1测试。在这种情况下,它可以得出结论,&&的结果为false,因为false && anything是false。 在测试2中发生了短路,但这并不改变结果。 - Chaos Crafter
5个回答

12
我不明白。由于等式左侧等于1,难道短路计算不应该成功吗?
不,绝对不是这样的。使用 && 的目的是只有当左右操作数都为 true 时,结果才为 true;短路计算意味着如果左操作数为 false,则不会评估右操作数,因为此时已知答案。
您应该阅读 JLS 的 15.2315.24 章节以获取更多详细信息:
条件与运算符&&类似于&(§15.22.2),但仅在其左操作数的值为true时才评估其右操作数。条件或运算符||类似于|(§15.22.2),但仅在其左操作数的值为false时才评估其右操作数。

谢谢...明白了...这有所不同...我需要练习才能让它变得“具体” :-) - Edward J Beckett

2
当使用布尔值时,按位运算符(|和&)与逻辑运算符(||和&&)类似,但以下不同:
- 在使用&&时,如果第一个参数为false,则第二个参数未计算,因为整个表达式必须为false。对于&,两个参数都会被计算。 - 在使用||时,如果第一个参数为true,则第二个参数未计算,因为整个表达式必须为true。对于|,两个参数都会被计算。
这就是我们所说的“短路”:在某些情况下,由于第一个参数的值,我们可以知道整个表达式的值而不计算第二个参数。
现在你要问为什么以下表达式是false:a == 1 && b == 3。好吧,这与短路无关;a = 1b = 2,所以陈述“a是1且b是2”显然是false,因为b不是2

简而言之:位运算符(|&)会对两个参数进行求值;逻辑运算符(||&&可以(但不总是)短路。 - NullUserException
@NullUserException 什么情况下它们不会短路? - arshajii
在楼主的例子中,它没有短路。 - NullUserException
@NullUserException 当然,因为 a == 1true - 逻辑运算符只要能够短路就会短路。 - arshajii
@NullUserException 我误解了,以为你在暗示即使可以时,逻辑运算符也有不短路的情况 - 是我的错误。无论如何,很高兴我们最终达成了共识! - arshajii

1
逻辑运算符||&&在评估第一个操作数后确定结果时会短路。对于||,如果第一个操作数的值为true,则是这种情况;对于&&,如果第一个操作数的值为false,则是这种情况。
如果||的第一个操作数的值为false,则仍然可以通过第二个操作数的值为true来产生总体结果为true。同样地,如果&&的第一个操作数的值为true,则如果第二个操作数的值为false,它仍然可以评估为false
在Java中,运算符|&不仅是位运算符(当应用于整数参数时),而且还是非短路逻辑运算符,无论第一个操作数的值如何都会评估两个操作数。

1

在IT领域,&和&&操作符都需要两边都为真,因此代码的行为符合预期。

唯一的区别在于,&会执行两边的操作,但是&&仅在第一个操作为假时才执行,因为右侧对于最终结果来说是无关紧要的。

对于类似下面的代码,这种效果非常重要:

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

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


这是一条很滑的鱼...;-) - Edward J Beckett
将变量更改为布尔值后,这一点变得非常清晰 :-) - Edward J Beckett

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

首先它会检查是否 a == 1 成立,因此必须继续检查是否 b == 3,这是不成立的,所以 true && falsefalse,因此您不会得到输出。

如果您有

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

它首先会检查是否b == 3,既然不是这种情况,就不必再看a == 1,因为false && whatever总是false,无论whatever是什么。

这回答了你的问题吗?


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接