为什么';Java有条件和条件or运算符的复合赋值版本吗?(&;&;=,| |=)
因此,对于布尔型上的二进制运算符,Java有为什么';Java有条件和条件or运算符的复合赋值版本吗?(&;&;=,| |=),java,conditional-operator,assignment-operator,short-circuiting,compound-assignment,Java,Conditional Operator,Assignment Operator,Short Circuiting,Compound Assignment,因此,对于布尔型上的二进制运算符,Java有&,,^,&和| 让我们在此简要总结一下他们的工作: 对于&,如果两个操作数值都是true,则结果值为true;否则,结果为false 对于|,如果两个操作数值都是false,则结果值为false;否则,结果为true 对于^,如果操作数值不同,则结果值为true;否则,结果为false &&运算符与&类似,但仅当其左侧操作数的值为真时,才对其右侧操作数求值 |运算符类似于|,但仅当其左侧操作数的值为false时才计算其右侧操作数 现在,在所
&
,
,^
,&
和|
让我们在此简要总结一下他们的工作:
&
,如果两个操作数值都是true
,则结果值为true
;否则,结果为false
对于|
,如果两个操作数值都是false
,则结果值为false
;否则,结果为true
对于^
,如果操作数值不同,则结果值为true
;否则,结果为false
&&
运算符与&
类似,但仅当其左侧操作数的值为真时,才对其右侧操作数求值
|
运算符类似于|
,但仅当其左侧操作数的值为false
时才计算其右侧操作数
现在,在所有5个变量中,有3个具有复合赋值版本,即|=
,&=
和^=
。所以我的问题很明显:为什么Java不同时提供&&
和|124;=
?我发现我需要的比我需要的更多
我不认为“因为太长了”是个好答案,因为Java有>>=
。这一遗漏肯定有更好的理由
发件人:
有12名指派操作员;[…]=*=/=%=+=-==>>=&=^=
有人评论说,如果实现了&&=
和|124;=
,那么它将是唯一不首先计算右侧的操作符。我认为复合赋值运算符首先计算右侧的概念是错误的
发件人:
形式为E1 op=E2
的复合赋值表达式等价于E1=(T)((E1)op(E2))
,其中T
是E1
的类型,除了E1
仅计算一次之外
作为证明,以下代码段抛出了一个NullPointerException
,而不是ArrayIndexOutOfBoundsException
int[] a = null;
int[] b = {};
a[0] += b[-1];
Java就是这样,因为C也是这样
现在的问题是为什么在C中如此,是因为当&和&&成为不同的操作符(在C从B下降之前的某个时候),操作符的&=种类被简单地忽略了
但是我的答案的第二部分没有任何来源来支持它。在Ruby中是允许的
如果我猜的话,我会说它不是经常使用的,所以没有实现。另一种解释可能是解析器只查看=前面的字符,我想不出比“它看起来难以置信的丑陋”更好的理由了 “&
”和“&&
”与“&&
”不同,这是一种快捷操作,如果第一个操作数为false,则不会执行此操作,“&
”将执行此操作(同时适用于数字和布尔值)
我确实同意存在更有意义,但如果不存在,也没那么糟糕。我猜它不在那里,因为C没有它
真的不能思考为什么。
< P>一个java的原创性是“简单的、面向对象的、熟悉的”。应用于这个案例,(=,C++有它,并且熟悉这方面意味着熟悉这两个的人)。
&&=不熟悉,也不简单,因为语言设计者不想考虑他们可以添加到语言中的每一个操作符,所以额外的操作符越少就越简单。主要是因为Java语法基于C(或至少是C族),在C语言中,所有这些赋值运算符都被编译成单个寄存器上的算术或按位汇编指令。赋值运算符版本避免了临时操作,可能在早期的非优化编译器上生成了更高效的代码。逻辑运算符(在C中称为)等价物(&&=
和|124;=
)与单个汇编指令没有如此明显的对应关系;它们通常扩展为测试和分支指令序列
有趣的是,像ruby这样的语言确实有| |=和&=
编辑:Java和C之间的术语不同可能是因为
x = false;
x &&= someComplexExpression();
看起来它应该赋值给x
并计算someComplexExpression()
,但从语法上看,计算取决于x
的值这一事实并不明显
另外,因为Java的语法是基于C的,没有人认为迫切需要添加这些操作符。无论如何,使用if语句可能会更好。原因
操作符&&
和|124;=
在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
第一个代码容易出错,因为许多开发人员认为无论f1()返回什么值,f2()
总是被调用。它就像bool isOk=f1()&&f2()
wheref2()
仅在f1()
返回true
时调用
如果开发人员希望仅在f1()
返回true
时调用f2()
,那么上面的第二个代码不太容易出错
Else&=
就足够了,因为开发人员希望总是调用f2()
:
相同的示例,但适用于&=
此外,JVM应该按如下方式运行上述代码
bool isOk = true;
isOK &= f1();
isOK &= f2(); //f2() always called whatever the f1() returned value
bool isOk = true;
if (!f1()) isOk = false;
if (!f2()) isOk = false; //f2() always called
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
======================
// 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 ...
foreach(item in coll)
{
bVal = bVal || fn(item); // not so elegant
}
foreach(item in coll)
{
bVal ||= fn(item); // elegant
}