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
的类型是什么? int
或 boolean
?
看我的回答,可能是按位-或者根本不是这里的意思!
【参考方案1】:
a |= b
与a = (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);
我认为matches
是boolean
;这意味着按位运算符的行为与逻辑运算符相同。
在循环的每次迭代中,OR
s 是 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 |= b
与a = a | b
相同
a | b
如果两个操作数都是整数类型(int、short 等),则为位运算符。 如果两个操作数都是布尔值,那么它就是一个布尔或。
当a
和b
都是布尔值时,a | b
和a || 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
时,您总是在评估a
和b
。使用 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 玩了太多位 :)
【讨论】:
这个算子有很多很好的用例。想象一下像addAll
或 removeAll
这样的方法在一个集合中,前提是您迭代参数中的集合。你 add
或 remove
在一个循环中,如果你实际上添加或删除了至少一个条目,你想返回 true
。以上是关于Java运算符:|=按位或并赋值示例[重复]的主要内容,如果未能解决你的问题,请参考以下文章