Java运算符:|=按位或并赋值示例[重复]

Posted

技术标签:

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

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

这是读取它的代码:

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

【问题讨论】:

能否向我们展示你阅读的代码? @talnicolas:用代码更新问题。 matches的类型是什么? intboolean? 看我的回答,可能是按位-或者根本不是这里的意思! 【参考方案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

以上是关于Java运算符:|=按位或并赋值示例[重复]的主要内容,如果未能解决你的问题,请参考以下文章

JAVA位赋值条件运算符等

java运算符

按位或运算符 | C中用于对齐内存块的用法[重复]

C语言移位运算符和 &=, ^=, |= ~= 的使用方法

Java运算符优先级

a|=b 是什么意思