布尔运算符的差异:& vs&&和| vs ||

时间:2010-10-25 12:31:59

标签: java bitwise-operators logical-operators boolean-logic

我知道&&||的规则,但&|是什么?请以一个例子向我解释这些。

11 个答案:

答案 0 :(得分:122)

这些是按位AND和按位OR运算符。

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.115.22.2)中指出了基于其输入的运营商的不同行为。

实际上,当两个输入都是布尔值时,运算符被认为是布尔逻辑运算符,其行为类似于条件 - 和(&&)和条件 - 或(||)运算符,除了事实他们不会短路,所以以下是安全的:

if((a != null) && (a.something == 3)){
}

这不是:

if((a != null) & (a.something == 3)){
}

“短路”意味着操作员不一定检查所有条件。在上面的例子中,&&仅在a不是null时检查第二个条件(否则整个语句将返回false,无论如何都要检查以下条件),所以a.something的陈述不会引起异常,或者被认为是“安全的”。

&运算符始终检查子句中的每个条件,因此在上面的示例中,当a.something实际上是a值时,null可能会被评估一个例外。

答案 1 :(得分:101)

我认为你在谈论两个运营商的逻辑意义,在这里你有一个表简历:

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

答案 2 :(得分:23)

我知道这里有很多答案,但它们看起来有点令人困惑。所以在从Java oracle学习指南做了一些研究后,我想出了三个不同的场景,即何时使用&& amp;或者&amp ;. 这三种情况是逻辑AND 按位AND 布尔AND

逻辑AND: 逻辑AND(又名条件AND)使用&& 运算符。它是短路的意思:如果左操作数为假,则不会评估右操作数。
示例:

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将不是计算

按位AND: 按位AND使用& 运算符。它用于对值进行按位运算。通过查看二进制数字操作来查看正在发生的事情要容易得多:

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的二进制表示排成一行时,按位AND预先形成只会产生二进制数,其中两个数字中的相同数字都为1.因此0101& ; 1100 == 0100.十进制数为5& 12 == 4.

布尔AND: 现在,布尔AND运算符的行为与按位AND和逻辑AND的行为相似且不同。我喜欢把它想象为在两个布尔值(或位)之间执行按位AND,因此它使用& 运算符。布尔值也可以是逻辑表达式的结果。

它返回true或false值,非常类似于逻辑AND,但与逻辑AND不同,它不会短路。原因是,它要按预先形成按位AND,它必须知道左右操作数的值。这是一个例子:

int x = 0;
if (false & (1 == ++x) {
    System.out.println("Inside of if");
}
System.out.println(x); //"1"

现在,当运行if语句时,即使左操作数为false,也会执行表达式(1 == ++ x)。因此,为x打印的值将为1,因为它会增加。

这也适用于逻辑OR(||),按位OR(|)和布尔OR(|) 希望这可以解决一些困惑。

答案 3 :(得分:7)

运营商&&和||是短路的,这意味着如果左手表达式的值足以确定结果,他们就不会评估他们的右手表达。

答案 4 :(得分:5)

&安培;和|提供与&& amp;相同的结果和||运营商。不同之处在于,他们总是评估表达式的两侧,其中&&和||停止评估第一个条件是否足以确定结果。

答案 5 :(得分:2)

在Java中,单个运算符&,|,^ ,!取决于操作数。如果两个操作数都是整数,则执行按位运算。如果两者都是布尔值,则执行“逻辑”操作。

如果两个操作数不匹配,则抛出编译时错误。

双重算子&&,||行为类似于单个对应物,但两个操作数必须是条件表达式,例如:

if((&lt; 0)&amp;&amp;(b&lt; 0)){...}或类似地, if((&lt; 0)||(b <0)){...}

source:java programming lang 4th ed

答案 6 :(得分:1)

&|是整数类型的按位运算符(例如int):http://download.oracle.com/javase/tutorial/java/nutsandbolts/op3.html

&&||仅对布尔值进行操作(并且短路,正如其他答案已经说过的那样)。

答案 7 :(得分:1)

也许知道在条件AND和条件OR在同一个表达式中使用之前总是评估按位AND和按位OR运算符。

if ( (1>2) && (2>1) | true) // false!

答案 8 :(得分:1)

&安培;&安培; ; ||是逻辑运算符....短路

&安培; ; |是布尔逻辑运算符....非短路

转向表达式执行的差异。无论左侧的结果如何,按位运算符都会评估双方。但是在使用逻辑运算符计算表达式的情况下,右手表达式的评估取决于左手条件。

例如:

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,

答案 9 :(得分:0)

如果计算涉及布尔&amp; 运算符的表达式,则会计算两个操作数。然后&amp;运算符应用于操作数。

当评估涉及&amp;&amp; 运算符的表达式时,将计算第一个操作数。如果第一个操作数的计算结果为false,则跳过第二个操作数的计算。

如果第一个操作数返回值true,则计算第二个操作数。如果第二个操作数返回值true,则&amp;&amp;然后将运算符应用于第一个和第二个操作数。

类似于|和||。

答案 10 :(得分:0)

虽然基本区别在于,&主要用于longintbyte的按位操作,其中它可用于掩码类型,即使您使用它而不是逻辑&&,结果也会有所不同。

在某些情况下,差异更明显:

  1. 评估某些表达式非常耗时
  2. 仅当前一个表达式为真时才能评估其中一个表达式
  3. 表达式有一些副作用(有意或无意)
  4. 第一点非常简单,它不会导致错误,但需要更多时间。如果你在一个条件语句中有几个不同的检查,那么将那些更便宜或更有可能失败的检查放在左边。

    对于第二点,请参阅此示例:

    if ((a != null) & (a.isEmpty()))
    

    null失败,因为评估第二个表达式会产生NullPointerException。逻辑运算符&&是惰性的,如果左操作数为假,则无论右操作数是什么,结果都是假的。

    第三点的示例 - 让我们说我们有一个使用DB而没有任何触发器或级联的应用程序。在我们删除Building对象之前,我们必须将Department对象的构建更改为另一个。我们还说操作状态作为布尔值返回(true =成功)。然后:

    if (departmentDao.update(department, newBuilding) & buildingDao.remove(building))
    

    这会评估两个表达式,从而即使部门更新由于某种原因失败也会执行构建删除。对于&&,它按预期工作,并在首次失败后停止。

    对于a || b,它等同于!(!a && !b),如果a为真,则停止,不再需要解释。