Java逻辑运算符短路

时间:2012-01-06 15:06:22

标签: java logical-operators

哪一组是短路的,这究竟是什么意味着复杂的条件表达式是短路的呢?

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);

}

10 个答案:

答案 0 :(得分:215)

&&||运营商“短路”,意味着如果没有必要,他们不会评估右侧。

&|运算符在用作逻辑运算符时,始终会对双方进行求值。

每个运营商只有一个短路案例,它们是:

  • 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;
}

第二个版本使用非短路操作符&,如果NullPointerExceptioninput,则会抛出null,但第一个版本将返回{{1}没有例外;

答案 1 :(得分:9)

SET A使用短路布尔运算符。

在布尔运算符的上下文中,“短路”意味着对于一组布尔值b1,b2,...,bn,只要第一个布尔值为真,短路版本就会停止评估(||)或false(&amp;&amp;)。

例如:

// 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)

答案 2 :(得分:4)

简单来说,短路意味着一旦您知道答案无法再改变就停止评估。例如,如果您正在评估一串逻辑AND并且在该链的中间发现FALSE,则无论结果是什么,您都知道结果将是错误的。链中的其余表达式。同样适用于OR的链:一旦发现TRUE,您就会立即知道答案,因此您可以跳过评估其余表达式。

您使用&&代替&||代替|向Java表明您想要短路。您帖子中的第一组是短路。

请注意,这不仅仅是为了节省几个CPU周期:在像这样的表达式中

if (mystring != null && mystring.indexOf('+') > 0) {
    ...
}

短路意味着正确操作和崩溃之间的区别(在mystring为空的情况下)。

答案 3 :(得分:4)

boolean a = (x < z) && (x == x);

这种类型会短路,这意味着如果(x < z)评估为false,则后者未评估,a将为false,否则&&也会评估(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()) { }
}

答案 4 :(得分:4)

短路意味着如果第一个操作员决定最终结果,则不会检查第二个操作员。

E.g。表达式是:真||假

如果是||,我们所需要的只是 其中一个 为True。因此,如果左侧是真的,那么检查右侧是没有意义的,因此根本不会检查。

同样,False&amp;&amp;真

如果是&amp;&amp;,我们需要 双方 为True。因此,如果左侧是False,则检查右侧没有意义,答案必须为False。因此,根本不会检查。

答案 5 :(得分:2)

Java提供了两个在大多数其他计算机语言中找不到的有趣的布尔运算符。这些AND和OR的二级版本称为短路逻辑运算符。从上表中可以看出,无论B是什么,当A为真时,OR运算符都会返回true。

类似地,无论B是什么,当A为假时,AND运算符都会导致错误。如果您使用||&&表单,而不是这些运算符的|&形式,Java将无需单独评估右侧操作数。当右侧操作数依赖于左侧操作数为true或false以便正常运行时,这非常有用。

例如,以下代码片段显示了如何利用短路逻辑评估来确保除法运算在评估之前有效:

if ( denom != 0 && num / denom >10)

由于使用了AND(&&)的短路形式,因此不存在导致运行时异常除以零的风险。如果这行代码是使用单个&版本的AND编写的,则必须对双方进行评估,从而在denom为零时导致运行时异常。

标准做法是在涉及布尔逻辑的情况下使用AND和OR的短路形式,将单字符版本专门用于按位运算。但是,这条规则有例外。例如,请考虑以下语句:

 if ( c==1 & e++ < 100 ) d = 100;

此处,使用单个&可确保增量操作将应用于e c是否等于1。

答案 6 :(得分:2)

逻辑OR: - 如果至少有一个操作数计算为true,则返回true。在应用OR运算符之前,将对两个操作数进行求值。

短路OR: - 如果左侧操作数返回true,则返回true而不评估右侧操作数。

答案 7 :(得分:2)

&&&运营商之间存在一些差异。同样的差异适用于|||。要记住的最重要的事情是&&逻辑运算符,仅适用于布尔操作数,而&按位运算符适用于整数类型和布尔值。

使用逻辑运算,您可以进行短路,因为在某些情况下(例如&&的第一个操作数为false,或||的第一个操作数为{{1} }),您不需要评估表达式的其余部分。这对于在访问字段或方法之前检查true以及在除以之前检查潜在的零来执行操作非常有用。对于复杂表达式,表达式的每个部分都以相同的方式递归计算。例如,在以下情况中:

(7 == 8) || ((1 == 3) && (4 == 4))

仅评估强调部分。要计算null,请先检查||7 == 8。如果是的话,右手边将被完全跳过。右侧仅检查true是否为1 == 3。既然如此,则不需要检查false,并且整个表达式的计算结果为4 == 4。如果左侧是false,例如true代替7 == 7,将跳过整个右侧,因为整个7 == 8表达式都是||,无论如何。

通过按位运算,您需要评估所有操作数,因为您实际上只是组合这些位。布尔值实际上是Java中的一位整数(无论内部是如何工作的),在一个特殊情况下,你可以对位运算符进行短路处理只是巧合。您不能使一般整数true&操作短路的原因是某些位可能处于打开状态,而某些位可能在任一操作数中都处于关闭状态。像|这样的东西产生零,但是如果不评估两个操作数,你就无法知道。

答案 8 :(得分:1)

if(demon!=0&& num/demon>10)

由于使用AND(&amp;&amp;)的短路形式,当恶魔为零时,不存在导致运行时异常的风险。

参考。 Herbert Schildt的Java 2第五版

答案 9 :(得分:0)

来自 docs.oracle 的文档

当逻辑表达式从左到右求值时,它们会使用以下规则测试可能的“短路”求值:

<块引用>

false && 任何东西都被短路评估为 false。

真||任何东西都是短路评估为真。

逻辑规则保证这些评估总是正确的。请注意,上述表达式的任何部分都不会被计算,因此不会产生任何副作用。

https://docs.oracle.com/cd/E57185_01/HIRUG/ch31s05s01.html