简体   繁体   English

我为什么要经常使用||而不是|和&&代替&?

[英]Why should I always use || instead of | and && instead of &?

Since I started programming Java, I've noticed that everyone was using && and || 自从我开始编写Java以来​​,我注意到每个人都在使用&&|| instead of & and | 而不是&| . What is the reason for this? 这是什么原因? I've been using && and || 我一直在使用&&|| all this time because I didn't know you can use & and | 所有这些因为我不知道你可以使用&| on booleans. 关于布尔人。

class A{static{
  boolean t = true;
  boolean f = false;
  System.out.println("&ff " + (f&&f) + " " + (f&f));
  System.out.println("&ft " + (f&&t) + " " + (f&t));
  System.out.println("&tf " + (t&&f) + " " + (t&f));
  System.out.println("&tt " + (t&&t) + " " + (t&t));
  System.out.println("|ff " + (f||f) + " " + (f|f));
  System.out.println("|ft " + (f||t) + " " + (f|t));
  System.out.println("|tf " + (t||f) + " " + (t|f));
  System.out.println("|tt " + (t||t) + " " + (t|t));
}}

As far as I can tell, they are the same: 据我所知,他们是一样的:

$ javac A.java && java A
&ff false false
&ft false false
&tf false false
&tt true true
|ff false false
|ft true true
|tf true true
|tt true true
Exception in thread "main" java.lang.NoSuchMethodError: main

Does using || 使用|| and && improve my code in any way? &&以任何方式改进我的代码?


As a simple test, I replaced hundreds of occurrences with the short form, and all of my unit tests still pass. 作为一个简单的测试,我用短格式替换了数百次,并且我的所有单元测试仍然通过。

|| and && uses short circuit evaluation &&使用短路评估

From same article 来自同一篇文章

Short-circuit evaluation, minimal evaluation, or McCarthy evaluation denotes the semantics of some Boolean operators in some programming languages in which the second argument is only executed or evaluated if the first argument does not suffice to determine the value of the expression 短路评估,最小评估或麦卡锡评估表示某些编程语言中某些布尔运算符的语义,其中第二个参数仅在第一个参数不足以确定表达式的值时执行或计算

Consider you have an object and you want to check one of its property for some value if you do: 假设您有一个对象,并且如果您执行以下操作,则需要检查其属性中的某个值:

if(obj != null & obj.ID == 1)

If your object obj is null you will get a null reference exception, since you used single & , the first condition evaluate to false , but it will still continue to the next condition and raising null reference exception. 如果你的对象obj为null,你将得到一个空引用异常,因为你使用了单个& ,第一个条件求值为false ,但它仍然会继续下一个条件并引发空引用异常。

If you used && then the second condition will never get evaluated, thus no exception. 如果您使用&&那么第二个条件永远不会被评估,因此没有例外。

if(obj != null && obj.ID == 1)

With your code you will not see any difference, but using bitwise | 使用您的代码,您将看不到任何差异,但使用按位| or & with multiple conditions would result in no short circuiting at all. &多个条件将导致没有短路的。

More Explanation. 更多解释。


consider that you following code: 考虑你下面的代码:

Boolean conditionA = 2 > 1; //some condition which returns true
if(conditionA | obj.SomeTimeConsumingMethod()){

}

Now in above code snippet, suppose you have an object with a method SomeTimeConsumingMethod which takes a lot of time in processing and returns true or false . 现在在上面的代码片段中,假设您有一个带有SomeTimeConsumingMethod方法的对象,该方法在处理过程中需要花费大量时间并返回truefalse If you use single | 如果你使用单个| it would evaluate both the conditions, since first conditionA is true it will process obj.SomeTimeConsumingMethod as well. 它将评估两个条件,因为第一个conditionAtrue它也将处理obj.SomeTimeConsumingMethod End result will be true for the whole if statement since | | ,整个if语句的结果都是true (OR) is used. (OR)被使用。

If your condition is using double || 如果您的条件是使用double || (OR Logical operator) (或逻辑运算符)

if(conditionA || obj.SomeTimeConsumingMethod())

Then the second condition obj.SomeTimeConsumingMethod() will not be evaluated. 然后将不评估第二个条件obj.SomeTimeConsumingMethod() This is short circuiting and that just saved you from executing some time consuming method. 这是短路的,这使您无法执行一些耗时的方法。 Still the end result is true regardless of what was returned from obj.SomeTimeConsumingMethod() . 无论从obj.SomeTimeConsumingMethod()返回什么,最终结果都是true的。

|| is logical or, where | 是合乎逻辑的,或如| is the bitwise operation or. 是按位运算或。 Same with && and & . &&&相同。 Use && and || 使用&&|| if you're in an if statement, and | 如果你在if语句中,和| or & if you're doing bit operations. &如果你正在做的位操作。

As has already been pointed out, && and || 正如已经指出的那样, &&|| do short-circuit evaluation. 进行短路评估。 & and | &| , with boolean operands, do the same operations but evaluate both operands regardless of the value of the first operand. ,使用布尔操作数,执行相同的操作,但无论第一个操作数的值如何,都要评估两个操作数。

There are cases where it matters which you use, such as when the left operand is a pre-condition for exception-free evaluation of the right hand operand. 在某些情况下,您使用它很重要,例如当左操作数是右侧操作数的无异常评估的前提条件时。

In most cases, it does not matter. 在大多数情况下,没关系。 I use && and || 我使用&&|| in those cases for readability, because that is the commoner choice. 在那些可读性的情况下,因为这是平民的选择。 Using & or | 使用&| with boolean operands would tend to make most Java programmers have to stop and think, and ask themselves whether there is some specific reason for it. 使用布尔操作数会使大多数Java程序员不得不停下来思考,并问自己是否有某些特定的原因。 I suspect it may be so common because of the inheritance from C and C++. 我怀疑它可能是如此常见,因为C和C ++的继承。

While you may get the "correct" result using the bit-wise operators, understand they do NOT represent the same thing. 虽然您可以使用逐位运算符获得“正确”结果,但要了解它们并不代表相同的事情。 For instance, this works 例如,这是有效的

public static void main(String[] args){
    int x = 5;
    int y = 9;
    System.out.println(x&y); // prints "1"
} 

However, this won't 但是,这不会

public static void main(String[] args){
    int x = 5;
    int y = 9;
    System.out.println(x&&y); // Compile error: java: operator && cannot 
                              //                be applied to int,int
}

The reason you don't use bit-wise operators for boolean logic is so that it's clear what the code is trying to do (as well as knowing that it actually works). 你没有对布尔逻辑使用逐位运算符的原因是它清楚了解代码尝试做什么(以及知道它实际上有效)。 Bit-wise operators are for manipulating bit values, where as boolean operators are for evaluating first-order logic statements. 逐位运算符用于操作位值,其中布尔运算符用于评估一阶逻辑语句。

While not the same, it is along the same reasoning for using .equals() vs == for comparison -- You don't want readers guessing as to what you meant to do. 虽然不一样,但使用.equals() vs ==进行比较也是同样的原因 - 你不希望读者猜测你的意图。 It may work in some instances (like comparing constant, hard-coded strings with == ), but it is poor form because what it says is that you are asking for instance equality as opposed to value equality, which is usually implied. 可能在某些情况下有效(比如使用==比较常量,硬编码的字符串),但它的形式很差,因为它说的是你要求实例相等而不是值相等,这通常是隐含的。 And using bit-wise operators implies you want to do bit manipulation, not first-order logic evaluation. 使用逐位运算符意味着您需要进行位操作,而不是一阶逻辑评估。

Arguing that short circuit evaluation is mandatory because of performance is weak. 认为短路评估是强制性的,因为性能很差。 You can make an argument that is almost as weak: that short circuit evaluation encourages extra nondeterminism and side channels. 你可以提出一个几乎同样弱的论点:短路评估会鼓励额外的非确定性和侧面渠道。 Random optimizations or random loss of nondeterminism/side channels, I'd prefer the latter. 随机优化或随机丢失非确定性/侧向通道,我更喜欢后者。

The only remaining argument is this: If your code base relies on short circuit behaviour, eg, the trick described by Habib ( if (obj != null && obj.ID == 1) ), then it may not be a good idea to start mixing in & , because programmers might get it confused with && . 唯一剩下的论点是:如果你的代码库依赖于短路行为,例如Habib描述的技巧( if (obj != null && obj.ID == 1) ),那么它可能不是一个好主意开始混合& ,因为程序员可能会得到它混淆&& ie, if you use & / | 即,如果你使用& / | everywhere, but only use && in a few places where you rely on short circuit evaluation, someone might make an error and put only & , it may be hard to spot. 无处不在,但只能在一些你依赖短路评估的地方使用&& ,有人可能会犯错误并且只放置& ,可能很难发现。 In this case, if you relied on && for performance instead of something like null checking, it may be harder to spot when someone accidentally puts & alone, since there would be no stacktrace. 在这种情况下,如果你依赖&&性能,而不是像null检查时,它可能更难被发现时,有人不小心把&孤独,因为就没有堆栈跟踪。

Does using || 使用|| and && improve my code in any way? 和&&以任何方式改进我的代码?

Let me demonstrate two examples on how the conditional boolean operators may improve your code. 让我演示两个关于条件布尔运算符如何改进代码的示例。 Compare 相比

if (a != null && a.equals("b") || z != null && z.equals("y"))
  System.out.println("correct");

with

boolean b1 = a != null, b2 = z != null;
if (b1) b1 = b1 & a.equals("b");
if (b2) b2 = b2 & z.equals("y");
if (b1 | b2) System.out.println("correct");

which is the best way I can think of relying solely on the logical boolean operators. 这是我能想到的唯一依赖于逻辑布尔运算符的方法。

Second, say you have two tests to perform: simpleTest() and heavyTest() , where the latter involves making an HTTP request and parsing the response. 其次,假设您要执行两个测试: simpleTest()heavyTest() ,后者涉及发出HTTP请求并解析响应。 You have 你有

if (simpleTest() & heavyTest()) System.out.println("success");
else throw new IllegalStateException();

and want to optimize it. 并希望优化它。 What would you rather do, this: 你还想做什么,这个:

if (simpleTest()) {
  if (heavyTest()) System.out.println("success");
  else throw new IllegalStateException("operation could not be completed");
} else throw new IllegalStateException("operation could not be completed"); 

this: 这个:

boolean b = simpleTest();
if (b) b = b & heavyTest());
if (b) System.out.println("success");
else throw new IllegalStateException("operation could not be completed");

or this: 或这个:

if (simpleTest() && heavyTest()) System.out.println("success");
else throw new IllegalStateException();

Why should I always use || 我为什么要经常使用|| instead of | 而不是| and && instead of &? 和&&代替&?

You shouldn't always use them, but you would do yourself a favor by making them your default because in 99.9% of uses they either don't hurt or make your code much better. 你不应该总是使用它们,但你可以通过将它们作为默认值来帮助自己,因为在99.9%的使用中它们不会伤害或使你的代码更好。 Reserve the logical operators for that 0.1% of cases where you truly do need their semantics. 为0.1%的情况保留逻辑运算符,确实需要它们的语义。


It has been mentioned elsewhere on this page that relying on the conditional evaluation of the right operand makes for counterintuitive code. 本页其他地方已经提到,依赖于对右操作数的条件评估会产生违反直觉的代码。 I refuse to accept such a view on intuition because, by definition, intuition is a learned skill . 我拒绝接受这种关于直觉的观点,因为根据定义,直觉是一种学习技巧 It is a facility bestowed to you by evolution to recognize a pattern in situations you encounter often, and to quickly (and subconciously) cut through to the correct conclusions. 它是一种通过进化赋予你的设施,可以在你经常遇到的情境中识别出一种模式,并迅速(并且下意识地)切入正确的结论。 One of the most important aspects of learning a language is acquiring the right intuitions. 学习语言最重要的一个方面就是获得正确的直觉。 The argument that a language feature is bad because it is counterintuitive to someone who looks at it for the first time cannot be taken seriously. 语言特征是坏的,因为它对于第一次看它的人来说是违反直觉的这个论点不能被认真对待。

In Java (and C/C++ if I remember correctly) the single "|" 在Java(和C / C ++,如果我没记错的话)单个“|” and "&" are bit-wise operators, not logical operators, they are used for completely different things. 而“&”是按位运算符,而不是逻辑运算符,它们用于完全不同的东西。

You use the "&&" and "||" 你使用“&&”和“||” for boolean statements 对于布尔语句

You use the "&" and "|" 你使用“&”和“|” for bit operations, given the following are binary numbers 对于位操作,给出以下二进制数

dont make assumption so fast. 不要这么快就做出假设。 It because this wont compile: 因为这不会编译:

  static boolean f(boolean a) {
    boolean x = (true|a) ? a : x;
    return x;
  }

Bro.java:6: variable x might not have been initialized
    boolean x = (true|a) ? a : x;
                           ^

and this will: 这将:

  static boolean f(boolean a) {
    boolean x = (true||a) ? a : x;
    return x;
  }

&& and || &&和|| are short cut operators. 是捷径运营商。 For example: 例如:

A && B 

Condition B will not be evaluated if condition A is false 如果条件A为假,则不评估条件B.

A || B

Condition B will not be evaluated if condition A is true 如果条件A为真,则不评估条件B.

You should always use shortcut operators for multiple conditions evaluation. 您应始终使用快捷运算符进行多个条件评估。 | | or & are used for bit-wise operations. 或&用于逐位操作。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM