Maybe I’m just being pedantic, but I think I’ve just found a mistake in the Java Tutorial. It claims:
All binary operators except for the assignment operators are evaluated from left to right; assignment operators are evaluated right to left.
The Java™ Tutorials » Language Basics » Operators
What is this supposed to mean? Evaluation from right to left would mean that when you have a line like the following you get the rightmost expression evaluated first:
int x = 42;
x += getNumber();
// The above would be equivalent to:
x = getNumber() + x;
But that’s not how Java actually evaluates this expression. And the JLS 12 (2019-02-08) clearly states in 15.26.2 that “the value of the left-hand operand is saved and then the right-hand operand is evaluated.”
This explains it best:
A compound assignment expression of the form
JLS 12, 15.26.2 Compound Assignment OperatorsE1 op= E2
is equivalent toE1 = (T) ((E1) op (E2))
, whereT
is the type ofE1
, except thatE1
is evaluated only once.
So the above code is actually equal to this:
x = (int) (x + getNumber());
Addition is commutative, so it doesn’t matter. But we also have /=
, which is not commutative. You can test this by using a static field for x
and some side effect (such as System.out.println
and some assignment to x
) in getNumber()
.
public class SomeClass {
static int x = 42;
public static void main(String[] args) {
// assignment operators are evaluated right to left?
x += getNumber();
// equal to:
// x = x + getNumber();
System.out.println(x);
}
static int getNumber() {
System.out.println("getNumber");
x = Integer.MIN_VALUE;
return 58;
}
}
This code will print 100. That’s because the old value of x
(42) is used. If x was evaluated after getNumber()
you would get -2147483590 instead.
Contrary to that the Tutorial says all assignments are evaluated left to right. But all the assignment operators are right-associative. That might be the reason for the mix-up.
There are 12 assignment operators; all are syntactically right-associative (they group right-to-left). Thus,
JLS 12, 15.26 Assignment Operatorsa=b=c
meansa=(b=c)
, which assigns the value ofc
tob
and then assigns the value ofb
toa
.
Example:
public static void main(String[] args) {
int x = 42, y = 58;
x += y *= x;
// equal to:
// x = x + (y = y*x);
System.out.println(x);
}
It would not make any sense if they were left-associative.
The Tutorial should be corrected to say:
All binary operators except for the assignment operators are grouped from left to right; assignment operators are grouped right to left.
Or:
All binary operators except for the assignment operators are left-associative; assignment operators are right-associative.