我知道 and 的规则&&
,||
但是&
and是什么|
?请用一个例子向我解释这些。
11 回答
这些是按位与和按位或运算符。
int a = 6; // 110
int b = 4; // 100
// Bitwise AND
int c = a & b;
// 110
// & 100
// -----
// 100
// Bitwise OR
int d = a | b;
// 110
// | 100
// -----
// 110
System.out.println(c); // 4
System.out.println(d); // 6
感谢 Carlos 指出 Java 语言规范(15.22.1、15.22.2 )中关于操作符基于其输入的不同行为的适当部分。
实际上,当两个输入都是布尔值时,运算符被视为布尔逻辑运算符,其行为类似于条件与 ( &&
) 和条件或 ( ||
) 运算符,除了它们不会短路,因此以下是安全的:
if((a != null) && (a.something == 3)){
}
这不是:
if((a != null) & (a.something == 3)){
}
“短路”是指操作员不必检查所有条件。在上面的例子中,只有在is not&&
时才会检查第二个条件(否则整个语句将返回 false,并且无论如何检查以下条件都没有实际意义),因此语句 of不会引发异常,或者被认为是“安全的” 。”a
null
a.something
运算符总是检查子句中的&
每个条件,因此在上面的示例中,a.something
可能会评估 whena
实际上是一个null
值,从而引发异常。
我认为您在谈论两个运算符的逻辑含义,这里有一个表格简历:
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
短路求值、最小求值或麦卡锡求值(在 John McCarthy 之后)是某些编程语言中某些布尔运算符的语义,其中仅当第一个参数不足以确定表达式:当 AND 函数的第一个参数计算结果为 false 时,整体值必须为 false;当 OR 函数的第一个参数计算结果为真时,整体值必须为真。
不安全意味着运算符始终检查子句中的每个条件,因此在上面的示例中,当 x 实际上是 0 值时,可能会评估 1/x,从而引发异常。
我知道这里有很多答案,但它们似乎都有点令人困惑。因此,在对 Java oracle 学习指南进行了一些研究之后,我提出了三种不同的场景,即何时使用 && 或 &。这三种情况是逻辑与、按位与和布尔与。
逻辑与:
逻辑与(又名条件与)使用&&运算符。它的短路含义:如果左操作数为假,则不会计算右操作数。
例子:
int x = 0;
if (false && (1 == ++x) {
System.out.println("Inside of if");
}
System.out.println(x); // "0"
在上面的示例中,x 的控制台打印的值为 0,因为 if 语句中的第一个操作数为 false,因此 java 不需要计算 (1 == ++x),因此不会计算 x。
按位与: 按位与使用&运算符。它用于对值执行按位运算。通过查看二进制数的运算可以更容易地了解发生了什么:
int a = 5; // 5 in binary is 0101
int b = 12; // 12 in binary is 1100
int c = a & b; // bitwise & preformed on a and b is 0100 which is 4
正如您在示例中看到的那样,当数字 5 和 12 的二进制表示排列在一起时,执行按位与只会产生一个二进制数,其中两个数字中的相同数字都有 1。因此 0101 和 1100 == 0100. 十进制是 5 & 12 == 4。
布尔 AND: 现在布尔 AND 运算符的行为与按位 AND 和逻辑 AND 的行为相似但不同。我喜欢将其视为在两个布尔值(或位)之间执行按位与,因此它使用&运算符。布尔值也可以是逻辑表达式的结果。
它返回一个真值或假值,很像逻辑 AND,但与逻辑 AND 不同,它没有短路。原因是它要执行按位与,它必须知道左右操作数的值。这是一个前任:
int x = 0;
if (false & (1 == ++x) {
System.out.println("Inside of if");
}
System.out.println(x); //"1"
现在,当运行该 if 语句时,将执行表达式 (1 == ++x),即使左操作数为假。因此,为 x 打印的值将是 1,因为它增加了。
这也适用于逻辑 OR (||)、按位 OR (|) 和布尔 OR (|) 希望这能消除一些混乱。
运算符 && 和 || 是短路的,这意味着如果左侧表达式的值足以确定结果,它们将不会计算右侧表达式。
& 和 | 提供与 && 和 || 相同的结果 运营商。不同之处在于它们总是计算表达式的两边,其中 && 和 || 停止评估第一个条件是否足以确定结果。
在 Java 中,单个运算符 &、|、^、! 取决于操作数。如果两个操作数都是整数,则执行按位运算。如果两者都是布尔值,则执行“逻辑”操作。
如果两个操作数不匹配,则会引发编译时错误。
双重运算符 &&, || 行为类似于它们的单个对应物,但两个操作数都必须是条件表达式,例如:
if (( a < 0 ) && ( b < 0 )) { ... } 或类似地, if (( a < 0 ) || ( b < 0 )) { ... }
来源:Java 编程语言第 4 版
也许知道按位 AND 和按位 OR 运算符总是在条件 AND 和条件 OR 用于同一表达式之前进行评估可能很有用。
if ( (1>2) && (2>1) | true) // false!
&
并且|
是整数类型的按位运算符(例如int
):http: //download.oracle.com/javase/tutorial/java/nutsandbolts/op3.html
&&
并且||
仅对布尔值进行操作(和短路,正如其他答案已经说过的那样)。
&& ; || 是逻辑运算符....短路
&; | 是布尔逻辑运算符.... 非短路
转到表达式执行的差异。位运算符评估两边,而不考虑左侧的结果。但是在使用逻辑运算符评估表达式的情况下,右手表达式的评估取决于左手条件。
例如:
int i = 25;
int j = 25;
if(i++ < 0 && j++ > 0)
System.out.println("OK");
System.out.printf("i = %d ; j = %d",i,j);
这将打印 i=26 ;j = 25,由于第一个条件为假,因此绕过右手条件,因为无论右手条件如何,结果都是假的。(短路)
int i = 25;
int j = 25;
if(i++ < 0 & j++ > 0)
System.out.println("OK");
System.out.printf("i = %d ; j = %d",i,j);
但是,这将打印 i=26; j=26,
如果计算涉及布尔&运算符的表达式,则计算两个操作数。然后将 & 运算符应用于操作数。
当计算涉及&&运算符的表达式时,将计算第一个操作数。如果第一个操作数的计算结果为假,则跳过第二个操作数的计算。
如果第一个操作数返回值 true,则计算第二个操作数。如果第二个操作数返回 true 值,则 && 运算符将应用于第一个和第二个操作数。
类似 | 和||。
虽然基本区别在于它&
主要用于按位运算long
,int
或者byte
它可以用于某种掩码,但即使您使用它而不是逻辑,结果也会有所不同&&
。
在某些情况下,这种差异更为明显:
- 评估某些表达式非常耗时
- 仅当前一个表达式为真时才能评估表达式之一
- 表达式有一些副作用(有意或无意)
第一点非常简单,它不会导致错误,但需要更多时间。如果您在一个条件语句中有多个不同的检查,请将那些更便宜或更有可能失败的检查放在左边。
对于第二点,请参见此示例:
if ((a != null) & (a.isEmpty()))
这失败了null
,因为评估第二个表达式会产生一个NullPointerException
. 逻辑运算符&&
是惰性的,如果左操作数为假,无论右操作数是什么,结果都是假的。
第三点的示例——假设我们有一个使用 DB 的应用程序,没有任何触发器或级联。在我们移除一个建筑物对象之前,我们必须将一个部门对象的建筑物更改为另一个。假设操作状态作为布尔值返回(true = 成功)。然后:
if (departmentDao.update(department, newBuilding) & buildingDao.remove(building))
这会评估这两个表达式,因此即使部门更新由于某种原因失败,也会执行建筑物移除。使用&&
,它按预期工作,并在第一次失败后停止。
至于a || b
,则等价于!(!a && !b)
,为真则停止a
,不再赘述。