为什么我们经常使用`||`而不是`|`,有什么区别?
我只是想知道为什么我们通常使用逻辑OR ||
两个布尔之间不是按位或|
,虽然他们都运作良好。
我的意思是,看看下面的内容:
if(true | true) // pass if(true | false) // pass if(false | true) // pass if(false | false) // no pass
if(true || true) // pass if(true || false) // pass if(false || true) // pass if(false || false) // no pass
我们可以使用|
而不是||
? 和&
和&&
一样的东西。
如果你使用||
和&&
forms,而不是|
和这些运算符的forms,Java不会单独评估右手操作数。
这是一个问题,如果你想短路评估或不 – 大部分时间你想。
说明短路的好处的一个好方法是考虑下面的例子。
Boolean b = true; if(b || foo.timeConsumingCall()) { //we entered without calling timeConsumingCall() }
正如杰里米和彼得所说的,短路的另一个好处是无效的参考检查:
if(string != null && string.isEmpty()) { //we check for string being null before calling isEmpty() }
更多信息
|
不会在布尔expression式中进行短路评估。 ||
将停止评估,如果第一个操作数是真的,但|
惯于。
另外, |
可以用来对byte / short / int / long值执行按位或运算。 ||
不能。
所以,仅仅以其他答案为例,在下面的防守检查中,短路是至关重要的:
if (foo == null || foo.isClosed()) { return; } if (bar != null && bar.isBlue()) { foo.doSomething(); }
使用|
而且可能会导致NullPointerException
被抛出。
逻辑||
和&&
只在必要时检查右侧。 |
并一直检查。
例如:
int i = 12; if (i == 10 & i < 9) // It will check if i == 10 and if i < 9 ...
重写它:
int i = 12; if (i == 10 && i < 9) // It will check if i == 10 and stop checking afterward because i doesn't = 10 ...
另一个例子:
int i = 12; if (i == 12 | i > 10) // It will check if i == 12 and it will check if i > 10 ...
重写它:
int i = 12; if (i == 12 || i > 10) // It will check if i == 12, it does, so it stops checking and executes what is in the if statement ...
另外注意一个常见的陷阱:非懒惰的操作符优先于懒惰的操作符,所以:
boolean a, b, c; a || b && c; //resolves to a || (b && c) a | b && c; //resolves to (a | b) && c
混合时要小心。
除了短路之外,还有一点要记住,对0或1以外的值进行按位逻辑操作与条件逻辑具有非常不同的含义。 而USUALLY与|
相同 和||
用&
和&&
得到非常不同的结果(例如2 & 4
是0 / false,而2 && 4
是1 / true)。
如果你从一个函数获得的东西实际上是一个错误代码,并且你正在testing非0性,这可能会非常重要。
在Java中,这不是一个问题,你必须明确地types化为布尔types或者与0等比较,但是在其他类似语言的语言中(C / C ++等),这可能会让人感到困惑。
另外请注意&和| 只能应用于整数types的值,而不是所有可以等同于布尔testing的值。 同样,在非Java语言中,可以用隐式!= 0
比较(指针,浮点数,带有operator bool()
等的对象等)的布尔值来使用相当多的东西,并且按位运算符几乎总是在这些情况下是荒谬的。
唯一一次你会使用|
或&
而不是||
或&&
是当你有非常简单的布尔expression式和短切(即一个分支)的成本大于您保存时通过不评估后面的expression式。
但是,这是一个微型优化,除了最低级别的代码之外,这种微型优化几乎不存在。
|| 是|时的逻辑或操作符 是按位还是操作符。
boolean a = true; boolean b = false; if (a || b) { } int a = 0x0001; a = a | 0x0002;
除了| 是一个按位运算符:|| 是一个短路操作 – 当一个元素是假的时候,它不会检查其他元素。
if(something || someotherthing) if(something | someotherthing)
如果某事是真的,|| 不会评估someotherthing,而| 会做。 如果if语句中的variables实际上是函数调用,则使用|| 可能会节省很多的性能。
a | b:无论如何评估b
一个|| b: 只有评估结果为假时才评估b
Java || 而&&运算符只在需要的时候评估布尔expression式的右边。 这被称为懒惰的评价 。
||的等效代码 运营商是
// Simulate // if(b||c) // doThis(); // else // doThat(); if(b) doThis(); else if(c) doThis(); else doThat(); // Similar for &&
这需要很多时间来评估某些expression式。 但是,有时您可能想要使用| 运营商:
public boolean updateGlobal(){ global = 2; return true; } if(false | updateGlobal()){ foo(); }
因为expression式的右边有一个副作用,我们希望它被评估,不pipe是什么。 这是一个很不好的做法。
| is the binary or operator || is the logic or operator
运营商||
和&&
被称为条件运算符 ,而|
和&
被称为按位运算符 。 他们服务不同的目的。
条件运算符仅适用于在左侧和右侧静态求值为boolean
expression式。
按位运算符可与任何数字操作数一起使用。
如果你想进行逻辑比较,你应该使用条件运算符 ,因为你会为代码添加某种types的安全性。
一个侧面说明:Java有| =但不是|| =
当你必须使用||的例子 是当第一个expression式是一个testing,看看第二个expression式是否会炸毁。 例如使用单个| 在下列情况下可能导致NPE。
public static boolean isNotSet(String text) { return text == null || text.length() == 0; }
|| 通过OR'ing两个值返回一个布尔值(这就是为什么它被称为LOGICAL或)
IE:
if (A || B)
如果A或B为真,返回true,否则返回false。
| 是对两个值执行按位运算的运算符。 为了更好地理解按位操作,你可以在这里阅读:
一个主要区别是|| 和“展示”短路“,所以只有在需要的时候才会对RHS进行评估。
例如
if (a || b) { path1... } else { path2.. }
如果a是真的,那么b不会被testing,并且path1被执行。 如果| 被使用,那么即使“a”是真实的,双方也将被评估。
看到这里和这里 ,多一点信息。
希望这可以帮助。
非短路可能是有用的。 有时候你想确定两个expression式是评估的。 例如,假设你有一个从两个单独列表中删除一个对象的方法。 你可能想要做这样的事情:
class foo { ArrayList<Bar> list1 = new ArrayList<Bar>(); ArrayList<Bar> list2 = new ArrayList<Bar>(); //Returns true if bar is removed from both lists, otherwise false. boolean removeBar(Bar bar) { return (list1.remove(bar) & list2.remove(bar)); } }
如果您的方法改为使用条件操作数,如果第一个列表返回false,则将无法从第二个列表中删除对象。
//Fails to execute the second remove if the first returns false. boolean removeBar(Bar bar) { return (list1.remove(bar) && list2.remove(bar)); }
这不是非常有用,(和大多数编程任务一样),你可以用其他方法实现它。 但是这是一个按位操作数的用例。
他们之间的基本区别是| 首先将值转换为二进制,然后执行位或操作。 同时,|| 不会将数据转换为二进制,只是在原始状态下执行该expression式。
int two = -2; int four = -4; result = two | four; // bitwise OR example System.out.println(Integer.toBinaryString(two)); System.out.println(Integer.toBinaryString(four)); System.out.println(Integer.toBinaryString(result)); Output: 11111111111111111111111111111110 11111111111111111111111111111100 11111111111111111111111111111110
阅读更多信息: http : //javarevisited.blogspot.com/2015/01/difference-between-bitwsie-and-logical.html#ixzz45PCxdQhk
| =按位或|| =逻辑或
通常在有预增和增后操作时使用。 看下面的代码:
package ocjpPractice; /** * @author tithik * */ public class Ex1 { public static void main(String[] args) { int i=10; int j=9; int x=10; int y=9; if(i==10 | ++i>j){ System.out.println("it will print in first if"); System.out.println("i is: "+i); } if(x==10 ||++x>y){ System.out.println("it will print in second if"); System.out.println("x is: "+x); } } }
输出:
它会先打印如果
我是:11它会打印在第二如果
x是:10
if
块相同但结果不同。 有|
,这两个条件将被评估。 但如果是||
,因为第一个条件已经是真的,它不会评估第二个条件。
有很多用例说明你为什么要去||
而不是|
。 一些用例必须使用|
操作员检查所有条件。
例如,如果您想检查表单validation,并且想要向用户显示所有包含错误文本的无效字段,而不仅仅是第一个无效字段。
||
运营商将是,
if(checkIfEmpty(nameField) || checkIfEmpty(phoneField) || checkIfEmpty(emailField)) { // invalid form with one or more empty fields } private boolean checkIfEmpty(Widget field) { if(field.isEmpty()) { field.setErrorMessage("Should not be empty!"); return true; } return false; }
因此,通过上面的代码片段,如果用户提交的表单中包含ALL空白字段, nameField
只会显示带有错误信息的nameField
。 但是,如果你改变它,
if(checkIfEmpty(nameField) | checkIfEmpty(phoneField) | checkIfEmpty(emailField)) { // invalid form with one or more empty fields }
无论true
情况如何,它都会在每个字段上显示正确的错误信息。
其他答案在覆盖操作符之间的function差异方面做得很好,但答案可能适用于现在存在的每一种C语言。 这个问题是用java标记的,所以我将尽力回答Java语言的具体和技术问题。
&
和|
可以是整数位运算符或布尔逻辑运算符。 按位和逻辑运算符( §15.22 )的语法是:
AndExpression: EqualityExpression AndExpression & EqualityExpression ExclusiveOrExpression: AndExpression ExclusiveOrExpression ^ AndExpression InclusiveOrExpression: ExclusiveOrExpression InclusiveOrExpression | ExclusiveOrExpression
EqualityExpression
的语法在§15.21中定义,它需要§§15.20中定义的RelationalExpression ,而§15.19和§4.3则分别定义了ShiftExpression和ReferenceType
。 ShiftExpression
需要ShiftExpression
定义的AdditiveExpression ,它继续向下钻取,定义基本的算术运算符,一元运算符等。ReferenceType深入到所有表示types的方式。 (虽然ReferenceType
不包括原始types,但最终需要原始types的定义,因为它们可能是数组的维度types,它是一个ReferenceType
。)
按位和逻辑运算符具有以下属性:
- 这些运算符具有不同的优先级,具有最高的优先级和
|
最低优先。- 每个操作符在语法上都是左关联的(每个组从左到右)。
- 如果操作数expression式没有副作用,每个操作符都是可交换的。
- 每个运算符都是关联的。
- 按位和逻辑运算符可用于比较两个数值types的操作数或两个
boolean
types的操作数。 所有其他情况都会导致编译时错误。
运算符作为位运算符还是逻辑运算符的区别取决于操作数是“可转换为原始整数types”( §4.2 )还是boolean
或Boolean
( §5.1.8 )。
如果操作数是整数types,则在两个操作数上执行二进制数字提升(第5.6.2节 ),并将操作数作为long
s或int
s进行操作。 操作的types将是(提升的)操作数的types。 在这一点上, &
将按位AND, ^
将按位异或,并|
将按位包含或。 ( §15.22.1 )
如果操作数是boolean
或Boolean
,则操作数将根据需要进行拆箱转换(第5.1.8节 ),操作types将为boolean
。 如果两个操作数都为true
,则结果为true
如果两个操作数都不相同,则结果为true
如果两个操作数都为true
则结果为true
。 (第15.22.2节 )
相反, &&
是“条件 – 运算符”( §15.23 )和||
是“有条件的或运营商”( §15.24 )。 他们的语法被定义为:
ConditionalAndExpression: InclusiveOrExpression ConditionalAndExpression && InclusiveOrExpression ConditionalOrExpression: ConditionalAndExpression ConditionalOrExpression || ConditionalAndExpression
&&
就像&
,除了只在左操作数为true
时才计算右操作数。 ||
就像|
除了只在左操作数为false
时才计算右操作数。
有条件的 – 并具有以下属性:
- 条件运算符在语法上是左关联的(它从左到右)。
- 条件运算符和运算符都是完全关联的副作用和结果值。 也就是说,对于任何expression式
a
,b
和c
,expression式((a) && (b)) && (c)
评估产生相同的结果,相同的副作用以相同的顺序发生,expression式(a) && ((b) && (c))
。- 条件操作符和操作符的每个操作数必须是
boolean
types或Boolean
types,否则会发生编译时错误。- 条件和expression式的types总是
boolean
。- 在运行时,首先评估左边的操作数expression式; 如果结果的types为
Boolean
型,则将进行拆箱转换( §5.1.8 )。- 如果结果值为
false
,则条件expression式的值为false
,不计算右边的操作数expression式。- 如果左侧操作数的值为
true
,则计算右侧expression式; 如果结果的types为Boolean
型,则将进行拆箱转换( §5.1.8 )。 结果值成为条件expression式的值。- 因此,
&&
计算&
boolean
操作数上的&
相同的结果。 它的区别仅在于右边的操作数expression式是有条件地而不是总是被评估的。
有条件的或者具有以下属性:
- 条件语句或运算符在语法上是左关联的(从左到右)。
- 条件或运算符完全关联于副作用和结果值。 也就是说,对于任何expression式
a
,b
和c
,评估expression式((a) || (b)) || (c)
((a) || (b)) || (c)
产生相同的结果,相同的副作用发生在相同的顺序,评估expression式(a) || ((b) || (c))
(a) || ((b) || (c))
。- 条件或运算符的每个操作数必须是
boolean
types或Boolean
types,否则会发生编译时错误。- 条件或expression式的types总是
boolean
。- 在运行时,首先评估左边的操作数expression式; 如果结果的types为
Boolean
型,则将进行拆箱转换( §5.1.8 )。- 如果结果值为
true
,则条件或expression式的值为true
并且不计算右侧的操作数expression式。- 如果左侧操作数的值为
false
,则计算右侧expression式; 如果结果的types为Boolean
型,则将进行拆箱转换( §5.1.8 )。 结果值变成条件或expression式的值。- 因此,
||
计算与|
相同的结果boolean
或Boolean
操作数。 它的区别仅在于右边的操作数expression式是有条件地而不是总是被评估的。
总之,正如@JohnMeagher在评论中一再指出的, &
和|
事实上,在布尔运算符或Boolean
运算符的特定情况下,布尔运算符是非短路的。 有了好的做法(即:没有次要影响),这是一个小小的区别。 但是,当操作数不是boolean
或Boolean
时,操作符的行为会有很大的不同:在Java编程的高级别中,位操作和逻辑操作根本无法比较。
1)。(expression1 | expression2),| 无论expression1的结果是true还是false,运算符都将评估expression2。
例:
class Or { public static void main(String[] args) { boolean b=true; if (b | test()); } static boolean test() { System.out.println("No short circuit!"); return false; } }
2)。(expression1 || expression2),|| 如果expression1为true,则运算符不会评估expression2。
例:
class Or { public static void main(String[] args) { boolean b=true; if (b || test()) { System.out.println("short circuit!"); } } static boolean test() { System.out.println("No short circuit!"); return false; } }
|| 是一个逻辑或和| 是一个比特明智的或。
Java运算符
| 是按位还是|| 是合乎逻辑的。
| 是一个按位运算符。 || 是一个逻辑运算符。
一个会拿两个或者两个。
人们会确定真相(这个OR)如果这是真的或者是真的,那么答案是正确的。
哦,当人们快速回答这些问题。