我在Java中有很长的比较,我想知道它们中的一个或多个是否真实。比较字符串很长且难以阅读,因此我将其分解以便于阅读,并自动使用快捷方式运算符|=
而不是negativeValue = negativeValue || boolean
。
boolean negativeValue = false;
negativeValue |= (defaultStock < 0);
negativeValue |= (defaultWholesale < 0);
negativeValue |= (defaultRetail < 0);
negativeValue |= (defaultDelivery < 0);
如果任何默认&lt; something&gt;我希望negativeValue
为真价值是负面的。这有效吗?它会做我期望的吗?我在Sun的网站或stackoverflow上看不到它,但Eclipse似乎没有问题,代码编译并运行。
同样,如果我想要执行多个逻辑交叉点,我可以使用&=
代替&&
吗?
答案 0 :(得分:191)
|=
是布尔逻辑运算符|
(JLS 15.26.2)的复合赋值运算符(JLS 15.22.2);不要与条件或||
(JLS 15.24)混淆。还有&=
和^=
分别对应于布尔逻辑&
和^
的复合赋值版本。
换句话说,对于boolean b1, b2
,这两个是等价的:
b1 |= b2;
b1 = b1 | b2;
逻辑运算符(&
和|
)与条件运算符(&&
和||
)之间的差异是前者不是“短路”;后者呢。那就是:
&
和|
始终评估两个操作数&&
和||
有条件地评估右操作数 ;只有当其值可能影响二进制操作的结果时,才会评估右操作数。这意味着在以下情况下不评估右操作数:
&&
的左操作数评估为false
false
)||
的左操作数评估为true
true
)回到原来的问题,是的,该构造是有效的,虽然|=
并不完全是=
和||
的等效快捷方式,但它会计算出你想要的内容。由于您使用的|=
运算符的右侧是一个简单的整数比较运算,|
没有短路的事实是无关紧要的。
有些情况下,当需要短路或甚至需要短路时,但您的情况不是其中之一。
不幸的是,与其他一些语言不同,Java没有&&=
和||=
。这在 Why doesn't Java have compound assignment versions of the conditional-and and conditional-or operators? (&&=, ||=) 。
答案 1 :(得分:16)
它不是||的“快捷方式”(或短路)运算符和&amp;&amp; (如果他们已经知道基于LHS的结果,他们将不会评估RHS)但是它将按照工作的方式做你想做的事。
作为区别的一个例子,如果text
为null,则此代码将正常:
boolean nullOrEmpty = text == null || text.equals("")
然而这不会:
boolean nullOrEmpty = false;
nullOrEmpty |= text == null;
nullOrEmpty |= text.equals(""); // Throws exception if text is null
(显然你可以针对那个特例做"".equals(text)
- 我只是想证明这个原则。)
答案 2 :(得分:3)
你可以只有一个陈述。在多行中表示它几乎与您的示例代码完全相同,只是不那么强制性:
boolean negativeValue
= defaultStock < 0
| defaultWholesale < 0
| defaultRetail < 0
| defaultDelivery < 0;
对于最简单的表达式,使用|
可能比||
更快,因为即使它避免进行比较,也意味着隐式使用分支,并且可能要贵很多倍。
答案 3 :(得分:1)
尽管对您的问题可能有点过分,但Guava库在Predicate
s上有一些很好的语法,并对/和Predicate
进行短路评估。
基本上,比较被转换为对象,打包到集合中,然后迭代。对于或谓词,第一个真实命中从迭代返回,反之亦然。和/。
答案 4 :(得分:1)
如果是关于可读性的话,我从测试逻辑中得到了分离测试数据的概念。代码示例:
// declare data
DataType [] dataToTest = new DataType[] {
defaultStock,
defaultWholesale,
defaultRetail,
defaultDelivery
}
// define logic
boolean checkIfAnyNegative(DataType [] data) {
boolean negativeValue = false;
int i = 0;
while (!negativeValue && i < data.length) {
negativeValue = data[i++] < 0;
}
return negativeValue;
}
代码看起来更冗长,不言自明。您甚至可以在方法调用中创建一个数组,如下所示:
checkIfAnyNegative(new DataType[] {
defaultStock,
defaultWholesale,
defaultRetail,
defaultDelivery
});
它比'比较字符串'更具可读性,并且还具有短路的性能优势(以阵列分配和方法调用为代价)。
修改强> 使用varargs参数可以简单地实现更高的可读性:
方法签名将是:
boolean checkIfAnyNegative(DataType ... data)
电话可能如下:
checkIfAnyNegative( defaultStock, defaultWholesale, defaultRetail, defaultDelivery );
答案 5 :(得分:1)
这是一个老帖子,但为了给初学者提供不同的视角,我想举个例子。
我认为类似复合运算符的最常见用例是+=
。我相信我们都写了这样的东西:
int a = 10; // a = 10
a += 5; // a = 15
这有什么意义?重点是避免使用样板并消除重复的代码。
因此,下一行完全相同,避免在同一行中键入变量b1
两次。
b1 |= b2;
答案 6 :(得分:0)
List<Integer> params = Arrays.asList (defaultStock, defaultWholesale,
defaultRetail, defaultDelivery);
int minParam = Collections.min (params);
negativeValue = minParam < 0;
答案 7 :(得分:0)
||逻辑布尔或左 |按位OR
| =按位包含OR和赋值运算符
| =不是shortcircit的原因是因为它是按位或不是逻辑OR。 也就是说:
C |= 2 is same as C = C | 2