Java中&和&&的区别是什么?

219

我一直认为Java中的&&运算符用于验证其布尔操作数是否都为true,而&运算符用于对两个整数类型执行位运算。

最近我了解到&运算符也可以用于验证其布尔操作数是否都为true,唯一的区别在于即使左侧操作数为false,它也会检查右侧操作数。

Java中的&运算符是否在内部进行了重载?或者背后还有其他概念吗?


3
可能是重复的问题,与 为什么我们通常使用 `||` 而不是 `|`,它们有什么区别? 相似。 - Blake Yarbrough
Double会尽可能地执行快捷方式。 - Nicholas Hamilton
在官方的sun/oracle文档中没有找到这方面的信息 :( - AlikElzin-kilaka
"短路"是这里的关键术语。 - AlikElzin-kilaka
15个回答

3

&&||被称为短路运算符。当它们被使用时,对于|| - 如果第一个操作数评估为true,则不会评估其余操作数。对于&& - 如果第一个操作数评估为false,则其余操作数根本不会被评估。

因此,在此示例中,如果a是true,则变量x不会被递增:if (a || (++x > 0))


0
几乎所有比较点都在所有答案中得到了很好的涵盖。我只想添加一个例子,以展示输出如何根据我们使用的运算符而改变。考虑下面的例子。
int a = 10;
if(++a==10 & ++a==12) {
    ++a;
}
System.out.println(a); //12

在上面的代码中,我们使用了位运算符&。因此,无论左右两个参数的结果如何,都会对它们进行计算。

所以,在if条件中,a会增加2次。但是由于条件不成立,它不会进入if循环,第3次增加也不会发生。因此,在这种情况下,a的最终值将变为12。

现在假设,在同样的例子中,如果我们使用了短路&&运算符。那么当++a==10被计算为false时,它将不会去检查第二个参数。因此,a的最终值将为11。

int a = 10;
if(++a==10 && ++a==12) {
    ++a;
}
System.out.println(a); //11

基于此,我们可以说按位 & 运算符的性能相对较低,与短路 && 运算符相比。因为按位运算符将评估两个参数,而不考虑第一个参数的结果。而 && 运算符将在第一个参数的结果为 false 时停止评估第二个参数。
这两者之间的另一个区别是,按位 & 运算符适用于布尔类型和整数类型。而短路 && 运算符仅适用于布尔类型。
我们可以写成:
System.out.println(4 & 5); // 4

但是如果我们试图像这样写,

System.out.println(4 && 5);

然后它会报错,显示:

二元运算符“&&”的操作数类型不匹配


0

所有的答案都很棒,似乎没有更多答案是需要的,但是我想指出一些关于“依赖条件”运算符的事情。

在使用 && 运算符的表达式中,一个条件—我们把它称为“依赖条件”—可能需要另一个条件为真才能使依赖条件的评估有意义。

在这种情况下,应该在 && 运算符之后放置依赖条件,以防止错误发生。

考虑表达式 (i != 0) && (10 / i == 2)。依赖条件 (10 / i == 2)必须出现在 && 运算符之后,以防止除以零的可能性。

另一个例子 (myObject != null) && (myObject.getValue() == somevaluse)

还有一件事情:&&|| 被称为短路求值,因为只有当第一个参数不足以确定表达式的值时,才会执行或计算第二个参数。
参考资料:Java™ How To Program (Early Objects), Tenth Edition

0

& 是一种位运算符,用于检查两个条件,因为有时我们需要同时评估两个条件。 而&& 逻辑运算符则在第一个条件返回 true 时才会进入第二个条件。


0
关于AND和OR运算符,Java拥有两种类型的求值方式,即短路求值完整求值。 < p > && || 短路求值

< p > 短路求值使您能够在整个结果可以从左侧值预测出来时,< strong>不评估 AND和OR表达式的右侧值。

int numberOne = 1;
int numberTwo = 2;
boolean result = false;

// left-side is false so the the overall result CAN be predicted without evaluating the right side.
// numberOne will be 1, numberTwo will be 2, result will be false
result = (numberOne > numberTwo) && (++numberOne == numberTwo);

System.out.println(numberOne); // prints 1
System.out.println(numberTwo); // prints 2
System.out.println(result);    // prints false


// left-side is true so the the overall result CAN NOT be predicted without evaluating the right side.
// numberOne will be 2, numberTwo will be 2, result will be true
result = (numberTwo > numberOne) && (++numberOne == numberTwo);

System.out.println(numberOne); // prints 2
System.out.println(numberTwo); // prints 2
System.out.println(result);    // prints true

& | ^ 完全求值

尽管在某些情况下可能可以预测结果,但有必要对右侧进行求值。

int numberOne = 1;
int numberTwo = 2;
boolean result = false;

// left-side is false so the the overall result will be false BUT the right side MUST be evaluated too.
// numberOne will be 2, numberTwo will be 2, result will be false
result = (numberOne > numberTwo) & (++numberOne == numberTwo);

System.out.println(numberOne); // prints 2
System.out.println(numberTwo); // prints 2
System.out.println(result);    // prints false

注意:

  1. 请注意,对于异或(^)操作符,没有短路,因为两侧始终需要确定整体结果。
  2. 请注意,短路求值的其他可能名称是“最小求值”和“麦卡锡求值”。
  3. 不建议在同一表达式中混合布尔逻辑和动作。
  4. &也可以作为位与运算符,非常学术化,可用于密码学。当两个位都为1时,结果为1;如果任意一个位不为1,则结果为0。(请查看以下代码)

位与示例:

byte a = 5;              // 00000101
byte b = 3;              // 00000011
byte c = (byte) (a & b); // 00000001 (c is 1)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接