提问人:Aaron 提问时间:1/6/2012 最后编辑:Chris MartinAaron 更新时间:3/2/2021 访问量:173970
Java 逻辑运算符短路
Java logical operator short-circuiting
问:
哪个集合短路,复数条件表达式短路到底是什么意思?
public static void main(String[] args) {
int x, y, z;
x = 10;
y = 20;
z = 30;
// T T
// T F
// F T
// F F
//SET A
boolean a = (x < z) && (x == x);
boolean b = (x < z) && (x == z);
boolean c = (x == z) && (x < z);
boolean d = (x == z) && (x > z);
//SET B
boolean aa = (x < z) & (x == x);
boolean bb = (x < z) & (x == z);
boolean cc = (x == z) & (x < z);
boolean dd = (x == z) & (x > z);
}
答:
SET A 使用短路布尔运算符。
在布尔运算符的上下文中,“短路”的含义是,对于一组布尔值 b1、b2、...、bn,一旦这些布尔值中的第一个为真 (||) 或假 (&&),短路版本将停止计算。
例如:
// 2 == 2 will never get evaluated because it is already clear from evaluating
// 1 != 1 that the result will be false.
(1 != 1) && (2 == 2)
// 2 != 2 will never get evaluated because it is already clear from evaluating
// 1 == 1 that the result will be true.
(1 == 1) || (2 != 2)
评论
&&
||
&&
||
&
|
||
&&
和运算符“短路”,这意味着如果没有必要,他们不会评估右侧。&&
||
当 and 运算符用作逻辑运算符时,始终计算两边。&
|
每个操作员只有一种短路情况,它们是:
false && ...
- 没有必要知道右边是什么,因为结果只能与那里的值无关false
true || ...
- 没有必要知道右边是什么,因为结果只能与那里的值无关true
让我们在一个简单的例子中比较一下这种行为:
public boolean longerThan(String input, int length) {
return input != null && input.length() > length;
}
public boolean longerThan(String input, int length) {
return input != null & input.length() > length;
}
第 2 个版本使用非短路运算符,并将抛出一个 if is ,但第 1 个版本将无异常地返回。&
NullPointerException
input
null
false
评论
简单来说,短路意味着一旦你知道答案不能再改变,就停止评估。例如,如果你正在评估一个逻辑 s 链,并且你发现该链的中间有一个,那么无论链中其余表达式的值是什么,你都知道结果将是错误的。s 链也是如此:一旦你发现了 ,你就会立即知道答案,因此你可以跳过计算其余的表达式。AND
FALSE
OR
TRUE
您通过使用 instead 而不是 代替 来向 Java 指示您想要短路。你帖子中的第一组是短路。&&
&
||
|
请注意,这不仅仅是为了节省几个 CPU 周期:在这样的表达式中
if (mystring != null && mystring.indexOf('+') > 0) {
...
}
短路意味着正确操作和崩溃之间的差异(在 mystring 为 null 的情况下)。
boolean a = (x < z) && (x == x);
这种会短路,这意味着如果评估为假,则后者不被评估,将是假的,否则也会评估。(x < z)
a
&&
(x == x)
&
是一个按位运算符,也是一个不短路的布尔 AND 运算符。
您可以通过以下方式测试它们(请参阅在每种情况下调用该方法的次数):
public static boolean getFalse() {
System.out.println("Method");
return false;
}
public static void main(String[] args) {
if(getFalse() && getFalse()) { }
System.out.println("=============================");
if(getFalse() & getFalse()) { }
}
评论
&
true & false
AND
OR
true & false
短路意味着如果第一个操作员决定最终结果,则不会检查第二个操作员。
例如,表达式为:True ||假
在||的情况下,我们所需要的只是True的一面之一。因此,如果左手边是真的,那么检查右手边就没有意义了,因此根本不会检查。
类似地,False & & True
在 && 的情况下,我们需要双方都为 True。因此,如果左边是 False,那么检查右边就没有意义了,答案必须是 False。因此,根本不会检查。
if(demon!=0&& num/demon>10)
由于使用了 AND(&&) 的短路形式,因此当 demon 为零时,不存在导致运行时异常的风险。
参考 Java 2 第五版,作者:Herbert Schildt
Java 提供了两个有趣的布尔运算符,这在大多数其他计算机语言中是找不到的。AND 和 OR 的这些辅助版本称为短路逻辑运算符。从上表可以看出,当 A 为 true 时,无论 B 是什么,OR 运算符都会产生 true。
同样,当 A 为 false 时,无论 B 是什么,AND 运算符都会导致 false。如果您使用这些运算符的 and 形式,而不是 and 形式,Java 将不会费心单独计算右侧操作数。当右操作数依赖于左操作数是真还是假才能正常运行时,这非常有用。||
&&
|
&
例如,以下代码片段演示如何利用短路逻辑计算来确保除法运算在计算之前有效:
if ( denom != 0 && num / denom >10)
由于使用了 AND() 的短路形式,因此不存在因除以零而导致运行时异常的风险。如果这行代码是使用 AND 的单一版本编写的,则必须对两端进行评估,从而在为零时导致运行时异常。&&
&
denom
在涉及布尔逻辑的情况下,使用 AND 和 OR 的短路形式是标准做法,而将单字符版本专门用于按位运算。但是,此规则也有例外。例如,请考虑以下语句:
if ( c==1 & e++ < 100 ) d = 100;
在这里,使用单个可确保将增量运算应用于是否等于 1。&
e
c
如果至少有一个操作数的计算结果为 true,则逻辑 OR :- 返回 true。在应用 OR 运算符之前,将对这两个操作数进行计算。
短路或 :- 如果左侧操作数返回 true,则返回 true,而不计算右侧操作数。
和运算符之间存在一些差异。同样的区别也适用于 和 。要记住的最重要的一点是,这是一个仅适用于布尔操作数的逻辑运算符,而是一个适用于整数类型和布尔值的按位运算符。&
&&
|
||
&&
&
使用逻辑运算,您可以进行短路,因为在某些情况下(例如存在的第一个操作数或存在的第一个操作数),您不需要计算表达式的其余部分。这对于执行诸如在访问字段或方法之前检查 for 以及在除以它们之前检查潜在零等操作非常有用。对于复杂表达式,表达式的每个部分都以相同的方式递归计算。例如,在以下情况下:&&
false
||
true
null
(7 == 8) || ((1 == 3) && (4 == 4))
只有强调的部分才会被评估。要计算 ,首先检查是否为 。如果是这样,右侧将被完全跳过。右侧仅检查是否为 。既然是,就不需要检查,整个表达式的计算结果为 。如果左侧是 ,例如 而不是 ,整个右侧将被跳过,因为整个表达式将无关紧要。||
7 == 8
true
1 == 3
false
4 == 4
false
true
7 == 7
7 == 8
||
true
使用按位运算时,您需要计算所有操作数,因为您实际上只是组合了这些位。布尔值在 Java 中实际上是一个位整数(无论内部如何工作),在这种特殊情况下,您可以对按位运算符进行短路,这只是一个巧合。不能使一般整数或运算短路的原因是,在任一操作数中,某些位可能处于打开状态,而某些位可能处于关闭状态。类似的东西产生零,但如果不计算两个操作数,你就无法知道这一点。&
|
1 & 2
docs.oracle 中的文档
当逻辑表达式从左到右计算时,使用以下规则测试它们是否可能进行“短路”计算:
false && 任何短路评估结果为 false。
真 ||任何短路评估结果均为 true。
逻辑规则保证这些评估始终是正确的。请注意,上述表达式的 anything 部分不会被计算,因此这样做的任何副作用都不会生效。
评论