【问题标题】:Java Operators : |= bitwise OR and assign example [duplicate]Java运算符:|=按位或并赋值示例[重复]
【发布时间】:2012-04-25 21:21:49
【问题描述】:

我刚刚浏览了某人编写的代码,我看到了 |= 的用法,查找 Java 运算符,它建议按位或分配操作,谁能解释并给我一个例子?

这是读取它的代码:

    for (String search : textSearch.getValue())
         matches |= field.contains(search);

【问题讨论】:

  • 能否向我们展示你阅读的代码?
  • @talnicolas:用代码更新问题。
  • matches的类型是什么? intboolean?
  • 看我的回答,可能是按位-或者根本不是这里的意思!

标签: java operators bit-manipulation variable-assignment


【解决方案1】:

a |= ba = (a | b) 相同

布尔变量

boolean 上下文中,它意味着:

if (b) {
    a = true;
}

也就是说,如果b 为真,那么a 将为真,否则a 将不被修改。

位运算

在某种程度上,这意味着在b 中设置的每个二进制位都将在a 中设置。在b 中清除的位将在a 中保持不变。

因此,如果在 b 中设置了第 0 位,它也会在 a 中设置,如下例所示:

  • 这将设置一个整数的底部位:

    a |= 0x01

  • 这将清除底部位:

    a &= ~0x01

  • 这将切换底部位:

    a ^= 0x01;

【讨论】:

  • 可以为a输入一些数值并说明详细操作。
【解决方案2】:
a |= b;

相同
a = (a | b);

它计算两个操作数的按位或,并将结果分配给左边的操作数。

解释您的示例代码:

for (String search : textSearch.getValue())
    matches |= field.contains(search);

我认为matchesboolean;这意味着按位运算符的行为与逻辑运算符相同。

在循环的每次迭代中,ORs 是 matches 的当前值以及从 field.contains() 返回的任何值。如果它已经为真,则将其设置为true,如果field.contains() 返回真,则

因此,它会计算在整个循环中对field.contains()任何 调用是否返回了true

【讨论】:

  • 你能输入一些 a 和 b 的值吗?
  • 哦,好吧,现在有点意义了
  • “这意味着按位运算符的行为与逻辑运算符相同”。实际上,逻辑运算符会短路。这里可能需要短路。
  • 还需要注意的是,如果contains()没有副作用,这是相当低效的。在循环中添加至少一个if (matches) { break; } 会更好......(虽然我认为getValue() 可能返回的搜索量太少以至于不会产生明显的差异......)
【解决方案3】:

这段代码:

int i = 5;
i |= 10;

等价于这段代码:

int i = 5;
i = i | 10;

同样,这段代码:

boolean b = false;
b |= true;

相当于这个:

boolean b = false;
b = b | true;

在第一个示例中,正在执行按位 OR。在第二个示例中,执行布尔 OR。

【讨论】:

    【解决方案4】:

    有没有可能是代码有bug,是故意的

    matches = matches || field.contains(search);

    如果至少一个字段包含search 变量,那么匹配项应该是true

    【讨论】:

    • 您的代码在功能上不一样 - 如果matches 已经为真,那么短路运算符将阻止评估field.contains(search)。 AFAIK |= 运营商不会那样做。
    • 也就是说我的代码是对原代码的优化
    • 仅当确实打算在这些情况下不调用 .contains() 时。
    • 你的意思是如果.contains()方法没有副作用
    • 是的,大多数情况下 - 在这种情况下可能无关紧要,但值得知道的是,对于布尔变量 a |= func()a = a | func() 相同,在功能上与 a = a || func() 不同,即使a 上的最终结果是相同的。
    【解决方案5】:

    a |= ba = a | b 相同

    a | b 如果两个操作数都是整数类型(int、short 等),则为位运算符。 如果两个操作数都是布尔值,那么它就是一个布尔或。

    ab 都是布尔值时,a | ba || b 之间的区别在于,在第一个中,双方都总是评估,在后面的b仅当a 为假时才评估。它是一种“快捷方式”运算符。

    这对于这样的情况很有用:

    if (a == null || a.equals(b)) { .. do something .. } // works
    
    if (a == null | a.equals(b)) { .. do something .. } // NPE if a is null
    

    另一方面,|| 实际上是作为字节码/机器码中的另一个条件跳转来实现的。在某些情况下,使用 | 运算符评估布尔条件可能会更快,以避免额外的跳转(以及分支预测等)。绝对是低级微基准测试来确定哪个更好(并且通常在大多数应用程序中并不重要)。

    当您执行a |= b 时,您总是在评估ab。使用 a ||= b 运算符并没有什么意义,因为等效的 a = a || b 将转换为:

    if (a) a = true;
    else if (b) a = true
    else a = false;
    

    ...由于|| 评估的条件性质。换句话说,如果a 已经为真,则不会评估b

    【讨论】:

      【解决方案6】:

      该代码 sn-p 是何时使用该运算符的一个糟糕示例。老实说,我想不出什么时候使用这个运算符的好例子,但这是我最好的尝试:

      boolean somethingIsTrue = testSomethingTrue();
      if(somethingIsTrue){
          //Do something
      }
      somethingIsTrue |= testSomethingElseTrue();
      if(somethingIsTrue){
          //Do something else
      }
      somethingIsTrue |= testSomethingElseTrue2();
      if(somethingIsTrue){
          //Do something else than something or something else
      }   
      

      注意:您需要 3 个 if,否则您可以只为第二个 if 执行 somethingIsTrue | testSomethingElseTrue()


      如果您想知道为什么不应该在第一个示例中使用运算符,原因如下:

      从性能的角度来看,它很差,因为它对每个循环进行比较和分配,而不仅仅是比较。此外,即使未来的迭代没有效果,它也会继续迭代(一旦将matches 设置为true,它就不会改变,String.contains 没有副作用)。

      仅基于此问题的存在,从可读性的角度来看,它也很差;)

      因此,代替那个 sn-p 我会去:

      for (String search : textSearch.getValue()){
          if(field.contains(search)){
              matches = true;
              break;
          }
      }
      

      顺便说一句,在我看来,当他(她)写这篇文章时,原来的编码员可能在code-golf 玩了太多 :)

      【讨论】:

      • 这个算子有很多很好的用例。想象一下像 addAllremoveAll 这样的方法在一个集合中,前提是您迭代参数中的集合。你 addremove 在一个循环中,如果你实际上添加或删除了至少一个条目,你想返回 true
      猜你喜欢
      • 2018-05-13
      • 2011-11-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-11-21
      • 1970-01-01
      • 2014-08-25
      相关资源
      最近更新 更多