布尔运算符的差异:&vs &&和| vs ||
我知道&&
和||
的规则 但是什么是&
和|
? 请用一个例子向我解释这些。
这些是按位与和运算符。
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 )中关于操作符根据其input的不同行为的适当部分。
实际上,当两个input都是布尔值时,运算符被认为是布尔逻辑运算符,其行为类似于条件运算符( &&
)和条件运算符( ||
),除了它们不会短路以下是安全的:
if((a != null) && (a.something == 3)){ }
这不是:
if((a != null) & (a.something == 3)){ }
我想你在谈论这两个运营商的逻辑意义,在这里你有一个表简历:
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
我知道这里有很多答案,但他们似乎有点混乱。 因此,在从Java的oracle学习指南做了一些研究之后,我想出了三种不同的时间来使用&&或者&。 这三种情况是逻辑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的二进制表示排列在一起时,那么按位“与”执行的操作将只会生成一个二进制数,其中两个数字中的相同数字都有一个1.因此,0101&1100 == 0100.小数点是5&12 == 4。
布尔AND:现在,布尔AND运算符对于按位AND和逻辑AND的行为相似且不同。 我喜欢把它看作是在两个布尔值(或位)之间执行一个按位与,因此它使用&运算符。 布尔值也可以是逻辑expression式的结果。
它返回一个真或假的值,就像逻辑AND一样,但与逻辑AND不同,它不会被短路。 原因在于,它要预先执行按位AND操作,它必须知道左侧和右侧操作数的值。 这里是一个例子:
int x = 0; if (false & (1 == ++x) { System.out.println("Inside of if"); } System.out.println(x); //"1"
现在,当if语句运行时,即使左操作数为假,expression式(1 == ++ x)也会被执行。 因此,为x打印出的值将为1,因为它已经增加。
这也适用于逻辑OR(||),按位OR(|)和布尔OR(|)希望这清除了一些混淆。
运算符&&和|| 是短路的,这意味着如果左侧expression式的值足以确定结果,则它们将不评估它们的右侧expression式。
&和| 提供与&&和||相同的结果 运营商。 不同之处在于它们总是评估expression式的两边,其中&&和|| 停止评估如果第一个条件足以确定结果。
&
和|
是整数types(如int
)的按位运算符: http : //download.oracle.com/javase/tutorial/java/nutsandbolts/op3.html
&&
和||
只对布尔运算(和其他的回答已经说过,短路)。
在Java中,单个运算符&,|,^,! 取决于操作数。 如果两个操作数都是整数,则执行按位操作。 如果两者都是布尔值,则执行“逻辑”操作。
如果两个操作数不匹配,则会引发编译时错误。
双运算符&&,|| 行为类似于单个对象,但是两个操作数都必须是条件expression式,例如:
((a <0)&&(b <0)){…}或类似地,如果((a <0)||(b <0)){…}
源代码:java编程lang 4th ed
也许有必要知道在相同expression式的条件AND和条件OR之前总是评估按位“与”运算符和按位OR运算符。
if ( (1>2) && (2>1) | true) // false!
&&; || 是逻辑运算符….短路
&; | 是布尔逻辑运算符….非短路
转向expression式执行上的差异。 按位运算符评估双方,而不考虑左手的结果。 但是在用逻辑运算符评估expression式的情况下,右手expression式的评估取决于左手的条件。
例如:
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,由于第一个条件是错误的,所以不pipe右手边的条件如何,右边的条件被忽略了,结果是错误的(短路)
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,
如果涉及布尔&操作符的expression式被评估,则两个操作数都被评估。 然后将&运算符应用于操作数。
当涉及&&运算符的expression式被评估时,第一个操作数被评估。 如果第一个操作数的计算结果为false,则跳过第二个操作数的计算。
如果第一个操作数返回值为true,则第二个操作数将被计算。 如果第二个操作数返回值为true,那么&&操作符将应用于第一个和第二个操作数。
类似于| 和||。
虽然基本的区别在于,用于按位操作的操作主要是long
, int
或者byte
,它们可以用作掩码types,但即使使用它而不是逻辑&&
,结果也可能不同。
在一些情况下差异更明显:
- 评估一些expression式是耗时的
- 只有当前一个是真的时,才能评估其中一个expression式
- expression式有一些副作用(有意或无意)
第一点非常简单,不会造成任何错误,但需要更多的时间。 如果在一个条件语句中有几个不同的检查,那么把那些更便宜或更可能失败的条件放在左边。
第二点,请看这个例子:
if ((a != null) & (a.isEmpty()))
这将失败为null
,因为评估第二个expression式会产生NullPointerException
。 逻辑运算符&&
是懒惰的,如果左操作数为假,那么无论右操作数是多less,结果都是假的。
第三点的例子 – 比方说,我们有一个应用程序,使用DB没有任何触发器或级联。 在删除Building对象之前,我们必须将一个Department对象的build筑物更改为另一个。 我们还要说操作状态是以布尔值(true = success)的forms返回的。 然后:
if (departmentDao.update(department, newBuilding) & buildingDao.remove(building))
这将对两个expression式进行评估,因此即使由于某种原因部门更新失败,也会执行build筑物清除。 使用&&
,它按预期工作,并在第一次失败后停止。
至于a || b
a || b
,它相当于!(!a && !b)
,如果a
为真,则停止,不需要更多解释。