存在非短路逻辑运算符的原因

时间:2012-02-13 17:20:18

标签: java logical-operators

boolean个操作数一起使用时,&|成为每个Section 15.22.2 of the JLS逻辑运算符。然而,与&&||不同,它们不会短路;他们总是评估双方。我有一个愚蠢的问题:当我们拥有效率更高的短路逻辑运算符时,为什么效率较低的非短路逻辑运算符(&|)仍在那里({{ 1}},&&)?我的意思是,与短路逻辑运算符相比,非短路逻辑运算符的实际用途是什么?换句话说,总是通过使用非短路逻辑运算符来评估双方的用法是什么?

6 个答案:

答案 0 :(得分:26)

更新回答

道歉,我在你的问题中错过了“逻辑”这个词,即使它 。 (我冒昧地用编辑来强调它。)

考虑您希望总是出现任何副作用的情况,无论左侧表达式是评估true还是false。例如,对比:

if (foo() & bar()) {
    // Only call this if both operations returned true
}

if (foo() && bar()) {
    // Only call this if both operations returned true
}

我们假设foobar都会产生我们想要的效果,无论foo是返回true还是{{1} }}。在上面的第一个中,我知道 false将始终被调用并产生效果。当然,在后者中,bar可能会或可能不会被调用。如果我们没有非短路版本,我们必须使用临时变量:

bar

你可能会争辩(我可能会)你应该无论如何,因为它很容易被误读boolean fooResult, barResult; fooResult = foo(); barResult = bar(); if (fooResult && barResult) { // ... } ,但我们去了,这是一个非实用的理由短路版本。

原始回答

您如何建议if (foo() & bar())(或&)成为短路运营商?使用|&&,它是有道理的,因为你正在处理布尔条件:它们可以是真或假,没有灰色阴影。但是||&处理的是位,而不是布尔值。结果是一个数字。我的意思是,如果左侧是|,我猜&无法评估右侧,如果左侧是0|同样无法评估它-bits-on适用于任何类型,但我没有看到太多指向使每个运算符的一个边缘情况显着(与254或更多其他情况相比)。

答案 1 :(得分:11)

有些情况下,布尔表达式的组件涉及您希望在所有情况下都要执行的操作。请考虑以下检查密码有效性的示例:

while ( !password.isValid() & (attempts++ < MAX_ATTEMPTS) ) {

    // re-prompt

}

如果由于短路而没有评估第二个条件,attempts永远不会增加。因此,可以实现更高的程序员灵活性。

答案 2 :(得分:2)

我的情况(C ++):

void setFields(Parameters bundle)
{
  if (setIfDifferent(&field1, bundle.value1) | 
      setIfDifferent(&field2, bundle.value2) |
      setIfDifferent(&field3, bundle.value3)) {
    storeState();
  }
}

setIfDifferent()如果对象的字段不同则设置新值,在这种情况下它返回true;或者在字段和新值相同的情况下返回false。所以,我们想尝试设置所有字段,如果其中任何字段发生了变化,那么我们想要存储新对象的状态。

答案 3 :(得分:1)

您可以在逻辑表达式中产生一些副作用,例如,您可以同时分配检查。如果仅评估一个部件,这可能会错误地工作。

现在不记得好的例子,但请记住,我有时需要“非短路”操作员。

嗯....下面是错误的例子,如果没有“非短路”,它将无法工作:

if( (object1=getInstance1()).getNumber() == 1 || (object2=getInstance2()).getNumber() == 2 ) {

    // do something which requires bot object1 and object2 assigned

}

答案 4 :(得分:0)

在我的例子中,我有两种方法比较两个不同但相关的对象(Object2是Object1的一个属性),看看是否有任何变化。如果更新了任何更新,则需要进行更新,但需要对两者进行评估,以便在两者都已更改的情况下修改对象。因此,单个管道&#34; OR&#34;比较是必需的。

EX:

if (compare(object1, currentObject1) | comparison(object2, currentObject2)) {
    updateObject1(object1);
}

答案 5 :(得分:0)

技术上,&amp;和|它们不符合逻辑,它们是按位操作符,当与布尔值相关时,它们成为逻辑运算符。

有时您希望在逻辑表达式中包含赋值表达式。

说:

if(a = (checkForSomeCondition()) | b = checkForAnotherCondition())
{
 //now do something here with a and b that has been cached
}

如果我使用了||,我将无法执行上述检查,并且必须将分配拆分为单独的语句。我在应用程序开发过程中从未遇到过这样的场景,但在编写算法时遇到过几次。

当然,您可以在逻辑表达式上使用一元运算符,或者通过引用将变量传递给谓词,但这些似乎不像上面那样常见。