为什么我们经常使用`||`而不是`|`,有什么区别?

我只是想知道为什么我们通常使用逻辑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。

| 是对两个值执行按位运算的运算符。 为了更好地理解按位操作,你可以在这里阅读:

http://en.wikipedia.org/wiki/Bitwise_operation

一个主要区别是|| 和“展示”短路“,所以只有在需要的时候才会对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和ReferenceTypeShiftExpression需要ShiftExpression定义的AdditiveExpression ,它继续向下钻取,定义基本的算术运算符,一元运算符等。ReferenceType深入到所有表示types的方式。 (虽然ReferenceType不包括原始types,但最终需要原始types的定义,因为它们可能是数组的维度types,它一个ReferenceType 。)

按位和逻辑运算符具有以下属性:

  • 这些运算符具有不同的优先级,具有最高的优先级和| 最低优先。
  • 每个操作符在语法上都是左关联的(每个组从左到右)。
  • 如果操作数expression式没有副作用,每个操作符都是可交换的。
  • 每个运算符都是关联的。
  • 按位和逻辑运算符可用于比较两个数值types的操作数或两个booleantypes的操作数。 所有其他情况都会导致编译时错误。

运算符作为位运算符还是逻辑运算符的区别取决于操作数是“可转换为原始整数types”( §4.2 )还是booleanBoolean ( §5.1.8 )。

如果操作数是整数types,则在两个操作数上执行二进制数字提升(第5.6.2节 ),并将操作数作为long s或int s进行操作。 操作的types将是(提升的)操作数的types。 在这一点上, &将按位AND, ^将按位异或,并| 将按位包含或。 ( §15.22.1 )

如果操作数是booleanBoolean ,则操作数将根据需要进行拆箱转换(第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式abc ,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式abc ,评估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式的值。
  • 因此, || 计算与|相同的结果 booleanBoolean操作数。 它的区别仅在于右边的操作数expression式是有条件地而不是总是被评估的。

总之,正如@JohnMeagher在评论中一再指出的, &| 事实上,在布尔运算符或Boolean运算符的特定情况下,布尔运算符是非短路的。 有了好的做法(即:没有次要影响),这是一个小小的区别。 但是,当操作数不是booleanBoolean时,操作符的行为会有很大的不同:在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运算符

| 是按位还是|| 是合乎逻辑的。

看一眼:

http://java.sun.com/docs/books/tutorial/java/nutsandbolts/operators.html

| 是按位包含的或

|| 是逻辑或

| 是一个按位运算符。 || 是一个逻辑运算符。

一个会拿两个或者两个。

人们会确定真相(这个OR)如果这是真的或者是真的,那么答案是正确的。

哦,当人们快速回答这些问题。