与boolean
个操作数一起使用时,&
和|
成为每个Section 15.22.2 of the JLS的逻辑运算符。然而,与&&
和||
不同,它们不会短路;他们总是评估双方。我有一个愚蠢的问题:当我们拥有效率更高的短路逻辑运算符时,为什么效率较低的非短路逻辑运算符(&
,|
)仍在那里({{ 1}},&&
)?我的意思是,与短路逻辑运算符相比,非短路逻辑运算符的实际用途是什么?换句话说,总是通过使用非短路逻辑运算符来评估双方的用法是什么?
答案 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
}
我们假设foo
和bar
都会产生我们想要的效果,无论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
}
如果我使用了||,我将无法执行上述检查,并且必须将分配拆分为单独的语句。我在应用程序开发过程中从未遇到过这样的场景,但在编写算法时遇到过几次。
当然,您可以在逻辑表达式上使用一元运算符,或者通过引用将变量传递给谓词,但这些似乎不像上面那样常见。