我一直认为Java中的&&
运算符用于验证其布尔操作数是否都为true
,而&
运算符用于对两个整数类型执行位运算。
最近我了解到&
运算符也可以用于验证其布尔操作数是否都为true
,唯一的区别在于即使左侧操作数为false,它也会检查右侧操作数。
Java中的&
运算符是否在内部进行了重载?或者背后还有其他概念吗?
我一直认为Java中的&&
运算符用于验证其布尔操作数是否都为true
,而&
运算符用于对两个整数类型执行位运算。
最近我了解到&
运算符也可以用于验证其布尔操作数是否都为true
,唯一的区别在于即使左侧操作数为false,它也会检查右侧操作数。
Java中的&
运算符是否在内部进行了重载?或者背后还有其他概念吗?
& <-- 验证两个操作数
&& <-- 如果第一个操作数的结果为false,则停止计算,因为整个表达式的结果将为false。
(x != 0) & (1/x > 1)
<-- 这意味着先计算 (x != 0)
,然后计算 (1/x > 1)
,最后计算 &。问题在于当x=0时,会抛出异常。
(x != 0) && (1/x > 1)
<-- 这意味着先验证(x != 0)
,只有在这是true的情况下,才会计算(1/x > 1)
,所以如果x=0,则完全安全,并且如果(x != 0)评估为false,则整个表达式直接评估为false而无需计算(1/x > 1)
。
编辑:
exprA | exprB
<-- 这意味着先计算 exprA
,然后计算 exprB
,最后计算 |
。
exprA || exprB
<-- 这意味着先验证 exprA
,只有在其结果为false
的情况下,才会计算 exprB
并执行 ||
。
除了不是惰性求值器而对两个操作数进行求值,我认为按位运算符的主要特征是像以下示例中比较操作数的每个字节:
int a = 4;
int b = 7;
System.out.println(a & b); // prints 4
//meaning in an 32 bit system
// 00000000 00000000 00000000 00000100
// 00000000 00000000 00000000 00000111
// ===================================
// 00000000 00000000 00000000 00000100
boolean a, b;
Operation Meaning Note
--------- ------- ----
a && b logical AND short-circuiting
a || b logical OR short-circuiting
a & b boolean logical AND not short-circuiting
a | b boolean logical OR not short-circuiting
a ^ b boolean logical exclusive OR
!a logical NOT
short-circuiting (x != 0) && (1/x > 1) SAFE
not short-circuiting (x != 0) & (1/x > 1) NOT SAFE
这取决于参数的类型...
对于整数参数,单个和符号("&")是按位与运算符。双个和符号("&&")仅适用于两个布尔型参数。
对于布尔参数,单个和符号构成无条件的 "逻辑与" 运算符,而双个和符号("&&")是 "条件逻辑与" 运算符。也就是说,单个和符号始终会评估两个参数,而双个和符号只有在第一个参数为 true 时才会评估第二个参数。
对于所有其他参数类型和组合,应该出现编译时错误。
&& 是短路运算符,而 & 是逻辑与运算符。
试一下这个。
String s = null;
boolean b = false & s.isEmpty(); // NullPointerException
boolean sb = false && s.isEmpty(); // sb is false
我认为我的答案可以更容易理解:
&
和&&
之间有两个区别。
如果它们被用作逻辑与
&
和&&
可以作为逻辑与,当&
或&&
的左右表达式结果都为真时,整个操作的结果可以为真。
当&
和&&
作为逻辑与时,有一个区别:
当使用&&
作为逻辑与时,如果左侧表达式的结果为假,则右侧表达式将不会执行。
以例子为例:
String str = null;
if(str!=null && !str.equals("")){ // the right expression will not execute
}
String str = null;
if(str!=null & !str.equals("")){ // the right expression will execute, and throw the NullPointerException
}
int x = 0;
int y = 2;
if(x==0 & ++y>2){
System.out.print(“y=”+y); // print is: y=3
}
int x = 0;
int y = 2;
if(x==0 && ++y>2){
System.out.print(“y=”+y); // print is: y=2
}
& 可以用作位运算符
&
可以用作按位与(Bitwise AND)运算符,&&
不能。
按位与(&)运算符仅在其操作数的两个位都为1时才产生1。然而,如果两个位都为0或两个位不同,则此运算符产生0。更准确地说,按位与(&)运算符返回1,只有当两个位都为1时,它返回0,只要任何一个位为0,它就返回0。
来自维基页面:
http://www.roseindia.net/java/master-java/java-bitwise-and.shtml
如JLS(15.22.2)所述:
当&、^或|运算符的两个操作数均为布尔类型或Boolean类型时,按位运算符表达式的类型为布尔类型。在所有情况下,必要时操作数都将进行自动拆装箱转换(§5.1.8)。
对于&,如果两个操作数的值都为true,则结果值为true;否则,结果为false。
对于^,如果操作数的值不同,则结果值为true;否则,结果为false。
对于|,如果两个操作数的值都为false,则结果值为false;否则,结果为true。
"诀窍"在于&
既是整数按位运算符,也是布尔逻辑运算符。因此,把它视为运算符重载的一个例子是合理的。
‘&&’ : 逻辑与运算符根据其参数的逻辑关系产生一个布尔值true或false。
例如:Condition1 && Condition2
如果Condition1是false,则 (Condition1 && Condition2) 将始终为 false,这就是为什么这个逻辑运算符也称为短路运算符,因为它不评估另一个条件。如果Condition1是false,则无需评估Condtiton2。
如果Condition1为true,则评估Condtion2,如果为true,则总体结果为true,否则为false。
‘&’ : 按位与运算符。如果输入位都为一,则在输出中产生一个一(1)。否则产生零(0)。
例如:
int a=12;// 12 的二进制表示为1100
int b=6;// 6 的二进制表示为0110
int c=(a&b); // (12&6) 的二进制表示为0100
c的值为4。
有关参考,请参阅http://techno-terminal.blogspot.in/2015/11/difference-between-operator-and-operator.html
boolean a = true;
boolean b = false;
boolean c = false;
boolean result1 = a || b && c; //is true; evaluated as a || (b && c)
boolean result2 = a | b && c; //is false; evaluated as (a | b) && c
使用布尔值时,这两者之间没有输出差异。你可以交换 && 和 & 或 || 和 | ,它永远不会改变表达式的结果。
区别在于处理信息的背景。当你使用表达式 "(a != 0) & (b != 0)",其中 a = 0,b = 1 时,会发生以下情况:
left side: a != 0 --> false
right side: b 1= 0 --> true
left side and right side are both true? --> false
expression returns false
当你写下表达式(a != 0) && (b != 0)
并且a=0,b=1时,会发生以下情况:
a != 0 -->false
expression returns false
少一些步骤,少一些处理,更好的编码体验,特别是在处理许多布尔表达式或复杂参数时。