为什么我们经常使用`||`而不是`|`,有什么区别?
我只是想知道为什么我们通常使用逻辑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
运营商|| 和&&被称为条件运算符 ,而| 和&被称为按位运算符 。 他们服务不同的目的。
条件运算符仅适用于在左侧和右侧静态求值为booleanexpression式。
按位运算符可与任何数字操作数一起使用。
如果你想进行逻辑比较,你应该使用条件运算符 ,因为你会为代码添加某种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的操作数或两个
booleantypes的操作数。 所有其他情况都会导致编译时错误。
运算符作为位运算符还是逻辑运算符的区别取决于操作数是“可转换为原始整数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))。- 条件操作符和操作符的每个操作数必须是
booleantypes或Booleantypes,否则会发生编译时错误。- 条件和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))。- 条件或运算符的每个操作数必须是
booleantypes或Booleantypes,否则会发生编译时错误。- 条件或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)如果这是真的或者是真的,那么答案是正确的。
哦,当人们快速回答这些问题。