存在非短路逻辑运算符的原因
与boolean
操作数一起使用时, &
和|
成为JLS第15.22.2节的 逻辑运算符。 不像&&
和||
但是,这些不会短路; 他们总是评估双方。 我有一个愚蠢的问题:当我们有更高效的短路逻辑运算符( &&
, ||
)时,为什么低效率的非短路逻辑运算符( &
, |
)仍然存在? 我的意思是,与短路逻辑运算符相反,非短路逻辑运算符的实际用法是什么? 换句话说,通过使用非短路逻辑运算符总是评估双方的用法是什么?
更新回答 :
道歉,我错过了“逻辑”这个词,尽pipe它在那里。 (我已经自由地强调了一下编辑。)
考虑一下你希望任何副作用总是发生的情况,而不pipe左侧expression式是否为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
都具有我们希望发生的效果,而不pipefoo
返回true
还是false
。 在上面的第一个中,我知道 bar
总是会被调用并起作用。 在后者当然, bar
可能会或可能不会被召唤。 如果我们没有非短路版本,我们不得不使用临时variables:
boolean fooResult, barResult; fooResult = foo(); barResult = bar(); if (fooResult && barResult) { // ... }
你可能会争论(我可能会),你应该这样做,因为if (foo() & bar())
太容易误读,但是我们有一个非短路版本的实用理由。
原始答案 :
你如何build议&
(或|
)做一个短路操作员? 用&&
和||
,这是有道理的,因为你在处理布尔条件:它们可以是真或假,没有灰色阴影。 但是&
和|
处理位,而不是布尔值。 结果是一个数字。 我的意思是,如果左边是0
,我猜&
不能评价右边,并且类似于|
如果左手边是无论什么types,都不能评价它,但是我没有看到多less点使每个运算符的一个边缘情况有意义(与254个或更多的其他情况相比) )。
在某些情况下,布尔expression式的组件涉及您想要在所有情况下执行的操作。 考虑下面的例子检查密码的有效性:
while ( !password.isValid() & (attempts++ < MAX_ATTEMPTS) ) { // re-prompt }
如果第二个条件由于短路而未被评估,则attempts
永远不会增加。 这样可以提高程序员的灵活性。
您可以在逻辑expression式中有一些副作用,例如您可以同时进行检查。 如果只评估一个部分,这可能会工作错误。
现在不记得好的例子,但是请记住我有时需要“非短路”的操作员。
嗯….下面是错误的例子,这将不工作没有“非短路”或:
if( (object1=getInstance1()).getNumber() == 1 || (object2=getInstance2()).getNumber() == 2 ) { // do something which requires bot object1 and object2 assigned }
我的情况(C ++):
void setFields(Parameters bundle) { if (setIfDifferent(&field1, bundle.value1) | setIfDifferent(&field2, bundle.value2) | setIfDifferent(&field3, bundle.value3)) { storeState(); } }
如果setIfDifferent()不同,setIfDifferent()会将对象的字段设置为新值,在这种情况下,它会返回true; 或者在字段和新值相同的情况下返回false。 所以,我们想要设置所有的字段,如果它们中的任何一个改变了,那么我们要存储新的对象的状态。
在我的情况下,我有两个方法比较两个不同但相关的对象(Object2是Object1的一个属性),以查看是否有任何更改。 更新需要发生,如果更新,但都需要评估,以便对象将被修改,如果两者都被更改。 因此,需要单个pipe道“或”比较。
EX:
if (compare(object1, currentObject1) | comparison(object2, currentObject2)) { updateObject1(object1); }
从技术上讲,&和| 是不合逻辑的,它们是位运算符,当与布尔运算符关联时变成逻辑运算符。
有时候你想在你的逻辑expression式中包含赋值expression式。
说:
if(a = (checkForSomeCondition()) | b = checkForAnotherCondition()) { //now do something here with a and b that has been cached }
如果我使用||,我不能执行上面的检查,并且不得不将分配分解成单独的语句。 在应用程序开发过程中,我从来没有遇到类似这样的场景,但是在编写algorithm的时候遇到了这个问题。
当然,你可以在逻辑expression式上使用一元运算符,或者通过引用将谓词传递给谓词,但是这些似乎不如上述那样普遍。