为什么 Java 没有条件和和条件或运算符的复合赋值版本?(&&=, ||=)

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2324549/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-29 20:37:01  来源:igfitidea点击:

Why doesn't Java have compound assignment versions of the conditional-and and conditional-or operators? (&&=, ||=)

javaconditional-operatorassignment-operatorshort-circuitingcompound-assignment

提问by polygenelubricants

So for binary operators on booleans, Java has &, |, ^, &&and ||.

所以对于布尔值的二元运算符,Java 有&, |, ^,&&||

Let's summarize what they do briefly here:

让我们在这里简要总结一下他们的工作:

For &, the result value is trueif both operand values are true; otherwise, the result is false.

For |, the result value is falseif both operand values are false; otherwise, the result is true.

For ^, the result value is trueif the operand values are different; otherwise, the result is false.

The &&operator is like &but evaluates its right-hand operand only if the value of its left-hand operand is true.

The ||operator is like |, but evaluates its right-hand operand only if the value of its left-hand operand is false.

对于&,结果值是true如果两个操作数值都是true; 否则,结果为false

对于|,结果值是false如果两个操作数值都是false; 否则,结果为true

对于^,结果值是true如果操作数值不同;否则,结果为false

&&操作是一样&,但是评估其右边的操作数只有在其左侧的值操作数true

||操作是一样|的,但评估其右边的操作数只有在其左侧的值操作数false

Now, among all 5, 3 of those have compound assignment versions, namely |=, &=and ^=. So my question is obvious: why doesn't Java provide &&=and ||=as well? I find that I need those more than I need &=and |=.

现在,在所有 5 个中,其中 3 个具有复合赋值版本,即|=,&=^=。所以我的问题很明显:为什么 Java 不提供&&=||=以及?我发现我需要那些比我更需要&=|=

And I don't think that "because it's too long" is a good answer, because Java has >>>=. There must be a better reason for this omission.

而且我不认为“因为它太长”是一个好的答案,因为 Java 有>>>=. 这种遗漏一定有更好的理由。



From 15.26 Assignment Operators:

15.26 赋值运算符

There are 12 assignment operators; [...] = *= /= %= += -= <<= >>= >>>= &= ^= |=

有 12 个赋值运算符;[...]= *= /= %= += -= <<= >>= >>>= &= ^= |=



A comment was made that if &&=and ||=were implemented, then it would be the only operators that do not evaluate the right hand side first. I believe this notion that a compound assignment operator evaluates the right hand side first is a mistake.

有人评论说,如果&&=||=被实现,那么它将是唯一不首先评估右侧的运算符。我相信复合赋值运算符首先评估右侧的这种想法是错误的。

From 15.26.2 Compound Assignment Operators:

15.26.2 复合赋值运算符

A compound assignment expression of the form E1 op= E2is equivalent to E1 = (T)((E1) op (E2)), where Tis the type of E1, except that E1is evaluated only once.

形式的复合赋值表达式E1 op= E2等价于E1 = (T)((E1) op (E2)),其中T是 的类型E1,只是E1只计算一次。

As proof, the following snippet throws a NullPointerException, not an ArrayIndexOutOfBoundsException.

作为证明,以下代码段抛出了一个NullPointerException,而不是一个ArrayIndexOutOfBoundsException

    int[] a = null;
    int[] b = {};
    a[0] += b[-1];

回答by olibre

Reason

原因

The operators &&=and ||=are not available on Javabecause for most of the developers these operators are:

运算符&&=||=Java上不可用,因为对于大多数开发人员来说,这些运算符是:

  • error-prone
  • useless
  • 容易出错
  • 无用

Example for &&=

示例 &&=

If Java allowed &&=operator, then that code:

如果 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

would be equivalent to:

将相当于:

bool isOk = true;
if (isOK) isOk = f1();
if (isOK) isOk = f2(); //f2() is called only when f1() returns true

This first code is error-pronebecause many developers would think f2()is always called whatever the f1() returned value. It is like bool isOk = f1() && f2();where f2()is called only when f1()returns true.

第一个代码容易出错,因为许多开发人员认为f2()无论 f1() 返回值如何,它总是被调用。就像bool isOk = f1() && f2();wheref2()只在f1()return时被调用true

If the developer wants f2()to be called only when f1()returns true, therefore the second code above is less error-prone.

如果开发人员希望f2()将被称为仅当f1()返回true,因此,第二代码是以上更不易出错。

Else &=is sufficient because the developer wants f2()to be always called:

Else&=就足够了,因为开发人员希望f2()始终被调用:

Same example but for &=

同样的例子,但对于 &=

bool isOk = true;
isOK &= f1();
isOK &= f2(); //f2() always called whatever the f1() returned value

Moreover, the JVM should run this above code as the following one:

此外,JVM 应将上述代码运行为以下代码:

bool isOk = true;
if (!f1())  isOk = false;
if (!f2())  isOk = false;  //f2() always called

Compare &&and &results

比较&&&结果

Are the results of operators &&and &the same when applied on boolean values?

是运营商的结果&&,并&同当布尔值应用?

Let's check using the following Java code:

让我们使用以下 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;
}

Output:

输出:

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
======================

Therefore YESwe can replace &&by &for boolean values ;-)

因此我们可以更换&&&布尔值;-)

So better use &=instead of &&=.

所以更好地使用&=而不是&&=.

Same for ||=

同为 ||=

Same reasons as for &&=:
operator |=is less error-prone than ||=.

与 for 相同的原因&&=:
运算符|=比 更不容易出错||=

If a developer wants f2()not to be called when f1()returns true, then I advice the following alternatives:

如果开发人员不想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();

or:

或者:

// 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 ...

回答by Josh Lee

Probably because something like

可能是因为像

x = false;
x &&= someComplexExpression();

lookslike it ought to be assigning to xand evaluating someComplexExpression(), but the fact that the evaluation hinges on the value of xisn't apparent from the syntax.

看起来它应该分配给x和评估someComplexExpression(),但评估取决于值的事实x从语法中并不明显。

Also because Java's syntax is based on C, and no one saw a pressing need to add those operators. You'd probably be better off with an if statement, anyway.

也因为 Java 的语法是基于 C 的,没有人看到添加这些运算符的迫切需要。无论如何,使用 if 语句可能会更好。

回答by EFraim

It is this way in Java, because it is this way in C.

在 Java 中是这样,因为在 C 中也是这样。

Now the question why it is so in C is because when & and && became different operators (sometime preceding C's descent from B), the &= variety of operators was simply overlooked.

现在的问题是,为什么在 C 中如此,因为当 & 和 && 成为不同的运算符时(有时在 C 从 B 下降之前),&= 运算符的种类被简单地忽略了。

But the second part of my answer does not have any sources to back it up.

但是我的答案的第二部分没有任何来源来支持它。

回答by p00ya

Largely because Java syntax is based on C (or at least the C family), and in C all those assignment operators get compiled to arithmetic or bitwise assembly instructions on a single register. The assignment-operator version avoids temporaries and may have produced more efficient code on early non-optimising compilers. The logical operator (as they are termed in C) equivalents (&&=and ||=) don't have such an obvious correspondence to single assembly instructions; they usually expand to a test and branch sequence of instructions.

主要是因为 Java 语法基于 C(或至少是 C 系列),而在 C 中,所有这些赋值运算符都被编译为单个寄存器上的算术或按位汇编指令。赋值运算符版本避免了临时性,并且可能在早期的非优化编译器上生成了更高效的代码。逻辑运算符(在 C 中称为)等价物 ( &&=and ||=) 与单个汇编指令没有如此明显的对应关系;它们通常扩展为测试和分支指令序列。

Interestingly, languages like ruby dohave ||= and &&=.

有趣的是,像 ruby这样的语言确实有 ||= 和 &&=。

Edit: terminology differs between Java and C

编辑:Java 和 C 之间的术语不同

回答by Yishai

One of Java's original aimswas to be "Simple, Object Oriented, and Familiar." As applied to this case, &= is familiar (C, C++ have it and familiar in this context meant familiar to someone who knows those two).

Java 的最初目标之一是“简单、面向对象和熟悉”。应用于这种情况时,&= 是熟悉的(C、C++ 有它,并且在这种情况下熟悉意味着熟悉这两个的人熟悉)。

&&= would not be familiar, and it would not be simple, in the sense that the language designers were not looking to think of every operator they could add to the language, so less extra operators are simpler.

&&= 不会很熟悉,也不会很简单,因为语言设计者并不想考虑他们可以添加到语言中的每个运算符,因此更少的额外运算符更简单。

回答by zanfilip

For Boolean vars, && and || would use short circuit evaluation while & and | don't, so you would expect &&= and ||= to also use short circuit evaluation. There is a good use case for this. Especially if you are iterating over a loop, you want to be fast, efficient and terse.

对于布尔变量,&& 和 || 将使用短路评估 while & 和 | 不要,所以你会期望 &&= 和 ||= 也使用短路评估。有一个很好的用例。尤其是当您在循环中进行迭代时,您希望快速、高效和简洁。

Instead of writing

而不是写作

foreach(item in coll)
{
   bVal = bVal || fn(item); // not so elegant
}

I want to write

我想写

foreach(item in coll)
{
  bVal ||= fn(item);    // elegant
}

and know that once bVal is true, fn() will not be called for the remainder of the iterations.

并且知道一旦 bVal 为真,fn() 将不会在剩余的迭代中被调用。

回答by NawaMan

'&' and '&&' are not the same as '&&' is a short cut operation which will not do if the first operand is false while '&' will do it anyway (works with both number and boolean).

' &' 和 ' &&' 不一样 ' &&' 是一个快捷操作,如果第一个操作数为 false 则&不会执行,而 ' ' 无论如何都会执行(适用于数字和布尔值)。

I do agree that it make more sense to exist but it is not that bad if it is not there. I guess it was not there because C does not have it.

我确实同意存在更有意义,但如果它不存在也没有那么糟糕。我想它不存在是因为 C 没有它。

Really can't think of why.

实在想不出为什么。

回答by Daniel Brückner

I cannot think of any better reason then 'It looks incredible ugly!'

我想不出比“它看起来非常丑陋”更好的理由了!

回答by zzawaideh

It is allowed in Ruby.

它在 Ruby 中是允许的。

If I were to guess, I would say that it is not frequently used so it wasn't implemented. Another explanation could be that the parser only looks at the character before the =

如果我猜的话,我会说它不经常使用,所以没有实施。另一种解释可能是解析器只查看 = 之前的字符

回答by Ely

&

&

verifies both operands, it's a bitwise operator. Java defines several bitwise operators, which can be applied to the integer types, long, int, short, char, and byte.

验证两个操作数,它是一个按位运算符。Java 定义了几个按位运算符,它们可以应用于整数类型,long、int、short、char 和 byte。

&&

&&

stops evaluating if the first operand evaluates to false since the result will be false, it's a logical operator. It can be applied to booleans.

如果第一个操作数的计算结果为假,则停止评估,因为结果将为假,这是一个逻辑运算符。它可以应用于布尔值。

The && operator is similar to the? & operator, but can make your code a bit more efficient. Because both expressions compared by the?&?operator must be?true?for the entire expression to be?true, there's no reason to evaluate the second expression if the first one returns?false. The?& operator always evaluates both expressions. The?&&?operator evaluates the second expression only if the first expression is true.

&& 运算符类似于? & 运算符,但可以使您的代码更有效率。因为由?&? 运算符比较的两个表达式都必须为?true? 才能使整个表达式为?true,如果第一个表达式返回?false,则没有理由评估第二个表达式。?& 运算符总是计算两个表达式。?&&? 运算符仅在第一个表达式为真时才计算第二个表达式。

Having a &&= assignment operator wouldn't really add new functionality to the language. The bitwise operator's arithmetic is much more expressive, you can do integer bitwise arithmetic, which includes Boolean arithmetic. The logical operators can merely do Boolean arithmetic.

拥有 &&= 赋值运算符不会真正为语言添加新功能。按位运算符的算术表达能力要强得多,您可以进行整数按位算术,其中包括布尔算术。逻辑运算符只能进行布尔运算。