【问题标题】:What is the difference between & and && in Java?Java中的&和&&有什么区别?
【发布时间】:2011-07-30 16:21:39
【问题描述】:

我一直以为Java中的&&操作符是用来验证它的两个布尔操作数是否都是true,而&操作符是用来对两个整数类型进行逐位运算的。

最近知道&操作符也可以用来验证它的两个布尔操作数是否都是true,唯一的区别是即使LHS操作数为假,它也会检查RHS操作数。

Java 中的& 运算符是否在内部重载?或者这背后是否还有其他概念?

【问题讨论】:

标签: java operators boolean bitwise-operators


【解决方案1】:

& &&

(x != 0) & (1/x > 1) (x != 0) 然后评估 (1/x > 1) 然后执行 &。问题是对于 x=0 这将引发异常。

(x != 0) && (1/x > 1) (x != 0) 并且只有当这是真的然后评估 (1/x > 1) 所以如果你有 x=0 那么这是完全安全的并且不会抛出任何异常 if (x != 0) 评估为 false 整个事情直接评估为 false 而不评估 (1/x > 1)

编辑:

exprA | exprB exprA 然后评估exprB 然后执行|

exprA || exprB exprA 并且只有当这是false 时才评估exprB 并执行||

【讨论】:

  • 写一个&或的原因是什么|在 if 语句中?它永远不会比 && 和 || 快。如果我们已经有答案,为什么还要检查第二个条件?请你提供一个现实的例子吗?
  • @Michu93:一个例子是,如果第二个条件是一个函数调用,它有一个你总是需要的副作用。由于通常应该避免副作用,因此只有在极少数情况下您需要这样做,而且我目前想不出一个现实的例子。
  • @Michu93 在实现与安全相关的代码,尤其是密码学时,使用这些运算符可以防止基于时间测量的侧信道攻击(不同的执行时间不同的结果)。有时,“恒定时间”比较比“更快”比较更有价值。
【解决方案2】:

除了不是通过评估两个操作数来作为惰性评估器之外,我认为位运算符的主要特征是比较操作数的每个字节,如下例所示:

int a = 4;
int b = 7;
System.out.println(a & b); // prints 4
//meaning in an 32 bit system
// 00000000 00000000 00000000 00000100
// 00000000 00000000 00000000 00000111
// ===================================
// 00000000 00000000 00000000 00000100

【讨论】:

  • 问题是关于逻辑布尔运算,而不是按位运算。
  • @EJP 它可以帮助像我这样只看标题的谷歌用户。
【解决方案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

【讨论】:

【解决方案4】:

这取决于参数的类型...

对于整数参数,单个 & 符号 ("&") 是“按位与”运算符。除了两个布尔参数之外,没有为任何东西定义双与号(“&&”)。

对于布尔参数,单与号构成(无条件)“逻辑与”运算符,而双与号(“&&”)是“条件逻辑与”运算符。也就是说,单 & 号总是计算两个参数,而双 & 号只有在第一个参数为真时才会计算第二个参数。

对于所有其他参数类型和组合,应该会发生编译时错误。

【讨论】:

    【解决方案5】:

    && 是短路运算符,而 & 是 AND 运算符。

    试试这个。

        String s = null;
        boolean b = false & s.isEmpty(); // NullPointerException
        boolean sb = false && s.isEmpty(); // sb is false
    

    【讨论】:

      【解决方案6】:

      它在JLS (15.22.2)中指定:

      当 &、^ 或 | 的两个操作数运算符的类型为 boolean 或 Boolean,则按位运算符表达式的类型为 boolean。在所有情况下,操作数都会根据需要进行拆箱转换(第 5.1.8 节)。

      对于&,如果两个操作数都为真,则结果值为真;否则结果为假。

      对于^,如果操作数的值不同,则结果值为真;否则结果为假。

      对于|,如果两个操作数的值都为假,则结果值为假;否则,结果为真。

      “诀窍”在于& 是一个整数位运算符以及一个布尔逻辑运算符。那么为什么不呢,将其视为 运算符重载 的示例是合理的。

      【讨论】:

        【解决方案7】:

        我觉得我的回答可以更容易理解:

        &&& 之间有两个区别。

        如果它们用作逻辑 AND

        &&&可以是逻辑AND,当&&&左右表达式结果都为真时,整个运算结果可以为真。

        &&& 为逻辑AND 时,有区别:

        当使用&&作为逻辑AND时,如果左表达式结果为假,则右表达式不会执行。

        举个例子:

        String str = null;
        
        if(str!=null && !str.equals("")){  // the right expression will not execute
        
        }
        

        如果使用&

        String str = null;
        
        if(str!=null & !str.equals("")){  // the right expression will execute, and throw the NullPointerException 
        
        }
        

        另一个例子:

        int x = 0;
        int y = 2;
        if(x==0 & ++y>2){
            System.out.print(“y=”+y);  // print is: y=3
        }
        

        int x = 0;
        int y = 2;
        if(x==0 && ++y>2){
            System.out.print(“y=”+y);  // print is: y=2
        }
        

        & 可用作位运算符

        & 可以用作按位运算符AND&& 不能。

        按位与“&”运算符产生 1 当且仅当 它的操作数是 1。但是,如果两个位都为 0 或两个位不同,则此运算符产生 0。更准确地说,如果两个位中的任何一个为 1,则按位与“&”运算符返回 1 并返回如果任何位为 0,则为 0。

        来自维基页面:

        http://www.roseindia.net/java/master-java/java-bitwise-and.shtml

        【讨论】:

          【解决方案8】:

          ‘&&’ : - 是一个逻辑与运算符,根据其参数的逻辑关系产生一个布尔值 true 或 false。

          例如:- Condition1 && Condition2

          如果 Condition1 为假,则 (Condition1 && Condition2) 将始终为假,这就是为什么此逻辑运算符也称为短路运算符的原因,因为它不评估另一个条件。如果 Condition1 为 false ,则无需评估 Condtiton2。

          如果 Condition1 为真,则评估 Condition2,如果为真则整体结果为真,否则为假。

          ‘&’ : - 是位与运算符。如果两个输入位都是一,它会在输出中产生一 (1)。否则它产生零 (0)。

          例如:-

          int a=12; // 12 的二进制表示是 1100

          int b=6; // 6的二进制表示是0110

          int c=(a & b); // (12 & 6) 的二进制表示是 0100

          c 的值为 4。

          供参考,请参考http://techno-terminal.blogspot.in/2015/11/difference-between-operator-and-operator.html

          【讨论】:

            【解决方案9】:

            &&|| 称为短路运算符。使用它们时,对于 || - 如果第一个操作数的计算结果为 true,则不计算其余操作数。对于 && - 如果第一个操作数的计算结果为 false,则其余部分根本不会被计算。

            所以 if (a || (++x > 0)) 在本例中,如果 a 为 true,则变量 x 不会递增。

            【讨论】:

              【解决方案10】:

              使用布尔值,两者之间没有输出差异。你可以交换 && 和 & 或 ||和 |它永远不会改变你的表达结果。

              区别在于处理信息的场景背后。当您将表达式“(a != 0) & ( b != 0)” 设置为 a= 0 和 b = 1 时,会发生以下情况:

              left side: a != 0 --> false
              right side: b 1= 0 --> true
              left side and right side are both true? --> false
              expression returns false
              

              当您在 a= 0 和 b = 1 时编写表达式 (a != 0) && ( b != 0) 时,会发生以下情况:

              a != 0 -->false
              expression returns false
              

              更少的步骤,更少的处理,更好的编码,尤其是在处理许多布尔表达式或复杂的参数时。

              【讨论】:

              • 如果操作数有副作用,它将改变表达式的整体结果。
              【解决方案11】:

              除了 && 和 ||短路,混合两种形式时还要考虑运算符优先级。 我认为每个人都不会立即明白 result1 和 result2 包含不同的值。

              boolean a = true;
              boolean b = false;
              boolean c = false;
              
              boolean result1 = a || b && c; //is true;  evaluated as a || (b && c)
              boolean result2 = a  | b && c; //is false; evaluated as (a | b) && c
              

              【讨论】:

                【解决方案12】:

                & 是一个位运算符,用于检查两个条件,因为有时我们需要评估两个条件。 但是 && 逻辑运算符在第一个条件为真时转到第二个条件。

                【讨论】:

                  【解决方案13】:

                  所有答案都是great,似乎no更多答案is needed 但我只是想指出一些关于 && 运算符的内容,称为 dependent condition

                  在使用运算符 && 的表达式中,条件(我们将其称为 dependent condition)可能需要另一个条件为真,以使相关条件的评估有意义。

                  在这种情况下,依赖条件应该放在 && 运算符之后以防止错误。

                  考虑表达式(i != 0) && (10 / i == 2)。依赖条件(10 / i == 2) 必须appear after && 运算符以防止被零除的可能性。

                  另一个例子(myObject != null) && (myObject.getValue() == somevaluse)

                  还有一件事:&&|| 被称为 short-circuit evaluation,因为第二个参数被执行或评估 only if first 参数从 not sufficedetermine value 987654341@

                  参考资料:Java™ How To Program (Early Objects), Tenth Edition

                  【讨论】:

                    【解决方案14】:

                    关于 AND 和 OR 运算符,Java 有两种类型的求值,即Short-Circuit evaluationfull evaluation

                    && || 短路评估

                    短路评估 使您能够不评估 AND 和 OR 表达式的右侧,此时可以从左侧值预测整体结果.

                    int numberOne = 1;
                    int numberTwo = 2;
                    boolean result = false;
                    
                    // left-side is false so the the overall result CAN be predicted without evaluating the right side.
                    // numberOne will be 1, numberTwo will be 2, result will be false
                    result = (numberOne > numberTwo) && (++numberOne == numberTwo);
                    
                    System.out.println(numberOne); // prints 1
                    System.out.println(numberTwo); // prints 2
                    System.out.println(result);    // prints false
                    
                    
                    // left-side is true so the the overall result CAN NOT be predicted without evaluating the right side.
                    // numberOne will be 2, numberTwo will be 2, result will be true
                    result = (numberTwo > numberOne) && (++numberOne == numberTwo);
                    
                    System.out.println(numberOne); // prints 2
                    System.out.println(numberTwo); // prints 2
                    System.out.println(result);    // prints true
                    

                    & | ^ 全面评估

                    虽然在某些情况下可以预测结果,但有必要评估右侧。

                    int numberOne = 1;
                    int numberTwo = 2;
                    boolean result = false;
                    
                    // left-side is false so the the overall result will be false BUT the right side MUST be evaluated too.
                    // numberOne will be 2, numberTwo will be 2, result will be false
                    result = (numberOne > numberTwo) & (++numberOne == numberTwo);
                    
                    System.out.println(numberOne); // prints 2
                    System.out.println(numberTwo); // prints 2
                    System.out.println(result);    // prints false
                    

                    注意:

                    1. 请注意,对于 XOR (^),没有短路,因为始终需要双方来确定总体结果。
                    2. 请注意,短路评估的其他可能名称是 minimal evaluationMcCarthy evaluation
                    3. 不建议在同一个表达式中混合布尔逻辑和动作
                    4. & 也可以充当位与运算符,非常学术,可用于密码学。当两个位都为1时,结果为1,或者其中一个位不为1,结果为0。(查看以下代码)

                    AND 位示例:

                    byte a = 5;              // 00000101
                    byte b = 3;              // 00000011
                    byte c = (byte) (a & b); // 00000001 (c is 1)
                    

                    【讨论】:

                      【解决方案15】:

                      几乎每个比较点都很好地涵盖在所有答案中。我只想添加一个例子。演示输出如何根据我们使用的运算符而变化。考虑下面的例子

                      int a = 10;
                      if(++a==10 & ++a==12) {
                          ++a;
                      }
                      System.out.println(a); //12
                      

                      在上面的代码中,我们使用了按位 & 运算符。因此,无论单个结果如何,它都会评估两个参数(左和右)。

                      所以a 将在if condition 内增加2 倍。但由于条件不会变为真,它不会进入 if 循环,也不会发生第三次增量。所以在这种情况下,a 的最终值将变为 12。

                      现在假设,在上面的同一个例子中,如果我们使用短路 && 运算符。然后在评估++a==10 为假后,它不会去检查第二个参数。因此,最终值将是 11。

                      int a = 10;
                      if(++a==10 && ++a==12) {
                          ++a;
                      }
                      System.out.println(a); //11
                      

                      基于此,我们可以说按位 & 运算符的性能与短路 && 运算符相比是相对较低的。由于按位运算符将评估两个参数,而不管第一个参数的结果如何。而 && 运算符将在第一个参数的结果为 false 时停止计算第二个参数。

                      这两者之间的另一个区别是,按位 & 运算符适用于布尔类型和整数类型。而短路 && 运算符仅适用于布尔类型。

                      我们可以写

                      System.out.println(4 & 5); // 4
                      

                      但是如果我们试着写成这样,

                      System.out.println(4 && 5);
                      

                      然后会报错说,

                      二元运算符'&&'的错误操作数类型

                      【讨论】:

                        猜你喜欢
                        • 2011-11-23
                        • 2022-12-04
                        • 2011-06-02
                        • 2010-09-19
                        相关资源
                        最近更新 更多