因此,对于在布尔二元运算符,Java有&
, |
, ^
, &&
和||
。
让我们来总结一下他们在这里简单做什么:
- JLS 15.22.2布尔逻辑运算符&,^和|
- JLS 15.23条件与运算&&
- JLS 15.24条件或运算符||
对于&
,结果值是true
如果两个操作数的值是true
; 否则,结果是false
。
对于|
时,结果值是false
如果两个操作数的值是false
; 否则,结果是true
。
对于^
,结果值是true
,如果操作数的值是不同的; 否则,结果是false
。
该&&
运算符是像&
但评估其右边的操作数只有在其左侧操作数的值是true
。
该||
运营商好像|
,但评估其右边的操作数只有在其左侧操作数的值是false
。
现在,所有5间,那些3有复合赋值的版本,即|=
, &=
和^=
。 所以我的问题是显而易见的:为什么不是Java提供&&=
和||=
呢? 我发现我需要那些比我更需要&=
和|=
。
我不认为“因为它太长”是一个很好的答案,因为Java具有>>>=
。 必须有这种遗漏一个更好的理由。
从15.26赋值运算符 :
有12个赋值运算符; [...] = *= /= %= += -= <<= >>= >>>= &= ^= |=
注释有人认为,如果&&=
和||=
得以实施,那么这将是不首先评估右手边的唯一运营商。 我认为这个概念是一个复合赋值操作符先计算右手边是一个错误。
从15.26.2复合赋值运算符 :
形式的化合物,赋值表达式E1 op= E2
相当于E1 = (T)((E1) op (E2))
其中T
是的类型E1
,除了E1
只计算一次。
为了证明这一点,下面的片段抛出一个NullPointerException
,而不是一个ArrayIndexOutOfBoundsException
。
int[] a = null;
int[] b = {};
a[0] += b[-1];
原因
运算符&&=
和||=
并非适用于Java的 ,因为大多数的开发者,这些运营商包括:
例如用于&&=
如果你的Java允许&&=
运算符,则该代码:
bool isOk = true; //becomes false when at least a function returns false
isOK &&= f1();
isOK &&= f2(); //we may expect f2() is called whatever the f1() returned value
将相当于:
bool isOk = true;
if (isOK) isOk = f1();
if (isOK) isOk = f2(); //f2() is called only when f1() returns true
这第一个代码是容易出错的 ,因为许多开发商会认为f2()
始终称为无论F1()返回的值。 它像bool isOk = f1() && f2();
其中f2()
被调用,只有当f1()
返回true
。
如果开发人员希望f2()
被调用,只有当f1()
返回true
,因此,第二代码是以上更不易出错。
否则&=
是足够的,因为开发人员希望f2()
将总是叫:
相同的例子,但对于&=
bool isOk = true;
isOK &= f1();
isOK &= f2(); //f2() always called whatever the f1() returned value
此外,JVM应为以下之一运行该上面的代码:
bool isOk = true;
if (!f1()) isOk = false;
if (!f2()) isOk = false; //f2() always called
比较&&
和&
结果
是运营商的结果&&
和&
一样当布尔值应用?
让我们来看看使用Java代码:
public class qalcdo {
public static void main (String[] args) {
test (true, true);
test (true, false);
test (false, false);
test (false, true);
}
private static void test (boolean a, boolean b) {
System.out.println (counter++ + ") a=" + a + " and b=" + b);
System.out.println ("a && b = " + (a && b));
System.out.println ("a & b = " + (a & b));
System.out.println ("======================");
}
private static int counter = 1;
}
输出:
1) a=true and b=true
a && b = true
a & b = true
======================
2) a=true and b=false
a && b = false
a & b = false
======================
3) a=false and b=false
a && b = false
a & b = false
======================
4) a=false and b=true
a && b = false
a & b = false
======================
所以是的 ,我们可以更换&&
通过&
布尔值;-)
因此,更好地利用&=
代替&&=
。
同为||=
同样的理由,作为&&=
:
操作者|=
是容易出错小于||=
。
如果开发者想f2()
不时称为f1()
返回true
,那么我建议以下选择:
// here a comment is required to explain that
// f2() is not called when f1() returns false, and so on...
bool isOk = f1() || f2() || f3() || f4();
要么:
// here the following comments are not required
// (the code is enough understandable)
bool isOk = false;
if (!isOK) isOk = f1();
if (!isOK) isOk = f2(); //f2() is not called when f1() returns false
if (!isOK) isOk = f3(); //f3() is not called when f1() or f2() return false
if (!isOK) isOk = f4(); //f4() is not called when ...
大概是因为像
x = false;
x &&= someComplexExpression();
看起来应该被分配给x
和评价someComplexExpression()
但该评价取决于的值的事实x
不是从语法显而易见。
也正因为Java的语法是基于C,也没有人看到,迫切需要补充的经营者。 你可能会是与if语句更好,反正。
正是这种方式在Java中,因为它是这样的C.
现在的问题是,为什么它是如此的C是因为当&和&&成为不同运营商(从B C的后裔之前的某个时候),在&=各种运营商简单地忽视。
但是我的回答的第二部分没有任何来源,以支持它。
一个Java的原始目的是要“简单,面向对象,和熟悉的。” 作为适用于这种情况下,&=熟悉(C,C ++有它在这方面,熟悉意味着熟悉的人谁知道这两个)。
&& =不熟悉,并且它不会是简单的,在这个意义上,语言的设计者并没有寻求认为他们可以添加到语言各运营商的,所以不太额外运营商更简单。
这主要是因为Java的语法是基于C(或至少是C家),并在C中的所有的赋值操作符被编译到算术或按位汇编指令对单个寄存器。 赋值操作符版本,避免临时对象,并可能会产生对早期非优化编译器效率更高的代码。 上述逻辑运算器(因为它们是用C称为)当量( &&=
和||=
)不具有这样的明显的对应于单个组件的指令; 它们通常扩大到指令测试和分支序列。
有趣的是,像Ruby语言确实有|| =和&& =。
编辑:术语Java和C之间不同
对于布尔乏,&&和|| 将使用短路评价而&和| 不这样做,所以你可能认为&& =和|| =也使用短路评价。 这是一个很好的用例此。 特别是如果你迭代一个循环,你想快速,高效和简洁。
相反,写作
foreach(item in coll)
{
bVal = bVal || fn(item); // not so elegant
}
我想写
foreach(item in coll)
{
bVal ||= fn(item); // elegant
}
并且知道,一旦BVAL是真实的,FN()将不会被要求对迭代的剩余部分。
“ &
”和“ &&
”是不一样的“ &&
”是短切操作时,如果第一个操作数是假,而“这不会做&
”会做吧(既数和布尔工作)。
我不同意,它更有意义的存在,但如果它不存在它不是那么糟糕。 我想这是不存在,因为C没有它。
实在想不出为什么。
它允许在Ruby中。
如果我猜,我会说,它不经常使用,因此没有实现。 另一种解释可能是,分析器只着眼于字符=前
我想不出什么更好的理由那么“它看起来不可思议的难看!”
&
验证两个操作数,它是位运算符。 Java定义几个位运算符,其可被施加到整型,长,整型,短整型,char和字节。
&&
如果停止第一个操作数的计算结果为假,因为其结果将是错误的,这是一个逻辑运算符评估。 它可以应用到布尔值。
&&运算符是类似与运营商,但可以让你的代码有点更高效。 因为通过比较两个表达式&操作必须是真实的,整个表达式是真实的,没有任何理由,如果第一个返回false评估第二表达式。 &运算符始终计算两个表达式。 &&运算符的计算结果只如果第一个表达式为真第二个表达式。
有一个&& =赋值运算符不会真的添加新功能的语言。 该位运算符的运算是更富于表现力,你可以做整数运算按位,其中包括布尔运算。 逻辑运算符可以仅仅做布尔运算。
A&B和&& b是不一样的东西。
一个&& b是布尔表达式,返回布尔值,并且a和b是一个位表达式返回int(如果a和b是整数)。
whare你觉得他们是一样的吗?
文章来源: Why doesn't Java have compound assignment versions of the conditional-and and conditional-or operators? (&&=, ||=)