&
、|
和^
是按位运算符,现在有人把它们称为逻辑运算符&&
、||
,我完全困惑了 - 同一个运算符有两个名称?已经有逻辑运算符&&
、||
,那么为什么还要使用&
、|
和^
呢?&
、|
和^
是按位运算符或逻辑运算符,取决于操作数的类型。如果操作数是整数,则运算符是按位运算符。如果它们是布尔值,则运算符是逻辑运算符。+
表示加法或字符串连接一样,取决于操作数的类型。或者就像“玫瑰”既可以是花朵,也可以是淋浴喷头。或者“猫”既可以是毛茸茸的动物,也可以是UNIX命令。单词在不同的上下文中有不同的含义。这对编程语言中使用的符号也是如此。)
已经有逻辑运算符
&&
、||
,为什么要使用&
、|
、^
?
对于前两个运算符,是因为它们在操作数何时/是否被计算方面具有不同的语义。这两种不同的语义在不同的情况下是必需的;例如:
boolean res = str != null && str.isEmpty();
对抗
boolean res = foo() & bar(); // ... if I >>need<< to call both methods.
< p > ^
运算符没有短路等效项,因为这根本就没有意义。
拥有语言参考文献是一回事,正确解释它又是另一回事。
我们需要正确解释事物。
即使Java文档说明&
既可以是按位运算符也可以是逻辑运算符,我们也可以提出论点,认为自上古以来自C以来,&
确实没有失去其逻辑运算符的魔力。也就是说,&
首先是一个内在的逻辑运算符(尽管这是一个非短路的运算符)
&
按字面+逻辑解析为逻辑操作。
为了证明这一点,自从C开始到现在(Java、C#、PHP等),这两行代码的行为都是相同的。
if (a == 1 && b)
if (a == 1 & b)
if ( (a == 1) && (b) )
if ( (a == 1) & (b) )
即使变量a
和b
都是整数,这个...
if (a == 1 & b)
...仍然会被解释为:
if ( (a == 1) & (b) )
if (a == 1 & b)
&
没有失去其逻辑(非短路)操作魔力,并且我们可以得出结论:Java延续了C的传统,使 &
仍然是一个逻辑操作。因此,我们可以说反过来,即可以通过应用括号将 &
重新用作位操作:if ( a == (1 & b) )
&
转换为位掩码操作。&
是一种按位运算符。a和b都是整数,但我不明白为什么以下位运算是Java中的编译错误:&
是一种按位运算符,在其操作数都是整数时使用。a和b都是整数,但我不明白为什么以下位运算是Java中的编译错误:if ( a == (1 & b) )
if ( a == (1 & b) )
想一想,如果C语言(以及任何复制其语法和语义的语言)没有引入&&
,现在可能会有人问:
如何使用
&
进行位运算?
&
本质上是一个逻辑运算符(非短路运算符),它不关心其操作数,即使两个操作数都是整数(例如掩码习惯用法),它也会像往常一样执行其业务(应用逻辑运算)。您只能通过应用括号来强制将其变为位运算。Java延续了C的传统如果Java的&
的操作数(整数1和整数变量b
)都是整数,则应该编译此代码:
int b = 7;
int a = 1;
if (a == 1 & b) ...
&
和|
是“本质上”逻辑运算符的断言是错误的。a = b & 42;
没有对a
或b
进行类型定义,使得&
成为逻辑运算符。很抱歉,但你的论点并不站得住脚,将整个段落加粗也无法改变这一点。 - Stephen Cif
操作符的。它涉及到 Java 中所有上下文中的操作符。 1a) 而且 JLS 在术语上没有对这些上下文进行任意区分。&
和|
在很久以前被用于两个目的,逻辑运算符和位运算符。如果你查看新生儿C语言(Java语言的模板),&
和|
被用作逻辑运算符。
但是,由于在同一语句中消除位运算和逻辑运算的歧义非常令人困惑,这促使Dennis Ritchie创建了一个单独的运算符(&&
和||
)用于逻辑运算符。
在这里检查“新生儿C”部分:http://cm.bell-labs.com/who/dmr/chist.html
您仍然可以将位运算符用作逻辑运算符,其保留的运算符优先级就是证据。阅读有关位运算符在新生儿C上作为逻辑运算符的过去历史。
关于证据,我写了一篇博客文章比较逻辑运算符和位运算符。如果你在实际程序中对比它们,就会自然而然地发现所谓的位运算符仍然是逻辑运算符,这一点是不言自明的:http://www.anicehumble.com/2012/05/operator-precedence-101.html 我还回答了一个与你的问题相关的问题:What is the point of the logical operators in C? 因此,没错,位运算符也是逻辑运算符,尽管是非短路逻辑运算符的版本。关于
已经有逻辑运算符&&、||,为什么还要使用&、|、^?
XOR 可以很容易地回答,它就像单选按钮,只允许一个,下面的代码返回 false。对于下面人为编造的代码示例,抱歉,已经证明同时喝啤酒和牛奶并不会有什么问题;-)
String areYouDiabetic = "Yes";
String areYouEatingCarbohydrate = "Yes";
boolean isAllowed = areYouDiabetic == "Yes" ^ areYouEatingCarbohydrate == "Yes";
System.out.println("Allowed: " + isAllowed);
对于XOR位运算符,没有短路等效的操作,因为需要评估表达式的两侧。
关于为什么需要使用&
和|
位运算符作为逻辑运算符,坦率地说,你很难找到需要使用位运算符(也称为非短路逻辑运算符)作为逻辑运算符的情况。如果您想要实现一些副作用并使代码紧凑(主观),则可以使用位运算符(即非短路逻辑运算符)来进行非短路逻辑操作,例如:
while ( !password.isValid() & (attempts++ < MAX_ATTEMPTS) ) {
// re-prompt
}
while ( !password.isValid() & attempts++ < MAX_ATTEMPTS ) {
// re-prompt
}
while ( ( !password.isValid() & attempts++ ) < MAX_ATTEMPTS ) {
// re-prompt
}
&
运算符(更普遍地称为位运算符,但实际上既可以是位运算符也可以是逻辑运算符(非短路))来实现副作用的非短路逻辑操作是聪明的(主观的),但并不被鼓励,这只是为了换取可读性而获得的一行节省效果。&
可以作为逻辑运算符的背景。 - Michael Buen&
逻辑运算符可以用作逻辑运算符,因为它被定义为这样。同样适用于&
位运算符。显然,Java从C中借鉴了语法,但它没有借鉴语义,这一点可以通过在Java中不能混合使用布尔和整数操作数来说明。 - Stephen Cbyte b1=(byte)0xFB; // that is -5
byte b2=2;
int i = b1 | b2<<8;
System.out.println((int)b1); // This prints -5
System.out.println(i); // This prints -5
原因:(int)b1在内部是0xFFFB,而b2<<8是0x0200,所以i将会是0xFFFB。
解决方案:
int i = (b1 & 0xFF) | (b2<<8 & 0xFF00);
System.out.println(i); // This prints 763 which is 0x2FB