First code snippet prints 2
public static void main(String args[]) throws Exception {
int[] a = { 1, 2, 3, 4 };
int[] b = { 2, 3, 1, 0 };
int val = (a = b)[3];
System.out.println( a [val ] );
}
Second code snippet outputs 1
public static void main(String args[]) throws Exception {
int[] a = { 1, 2, 3, 4 };
int[] b = { 2, 3, 1, 0 };
int val;
System.out.println(a[val = ((a = b)[3])]);
}
What is going on?
The output is reasonable. Let's expand the two complicated lines into several separate statements. First snippet:
// This...
int val = (a = b)[3];
// Becomes...
a = b;
int val = a[3]; // 0
So printing a[val]
will print a[0]
, which is now 2.
The second snippet is more complicated. The tricksy bit is that "the array we're indexing into" is evaluated before the rest of the side-effects. So:
// This...
System.out.println(a[val = ((a = b)[3])]);
// Becomes...
int[] tmp = a; // So tmp is { 1, 2, 3, 4 }
a = b;
val = a[3]; // 0
System.out.println(tmp[val]); // 1
JLS section 15.10.4 goes into more detail about this. The important parts here are:
At run time, evaluation of an array access expression behaves as follows:
- First, the array reference expression is evaluated. If this evaluation completes abruptly [...] evaluated.
- Otherwise, the index expression is evaluated. If this evaluation completes abruptly [...]
- Otherwise, if the value of the array reference expression is null [...]
- Otherwise, the value of the array reference expression indeed refers to an array. If the value of the index expression is less than zero [...]
- Otherwise, the result of the array access is the variable of type T, within the array, selected by the value of the index expression.
See more on this question at Stackoverflow