Reputation: 6665
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?
Upvotes: 4
Views: 325
Reputation: 1090
first:
int[] a = { 1, 2, 3, 4 };
int[] b = { 2, 3, 1, 0 };
int val = (a = b)[3];
/**
* a=b => a = { 2, 3, 1, 0 };
* val = a[3] = 0;
* a[val] => a[0] =>2;
**/
System.out.println( a [val ] ); //2
second:
int[] a = { 1, 2, 3, 4 };
int[] b = { 2, 3, 1, 0 };
int val;
System.out.println(a[val = ((a = b)[3])]);
/**
* a[val = ((a = b)[3])]
* => a[val=(b[3])] val is not used here
* => a[b[3]] => a[0] => 1
**/
Upvotes: 1
Reputation: 16833
So in the first example, b is assigned to a, val equals the 4th value of b, 0, and then we print the value with index 0, 2. You got this.
In the second example, as all operations are done in one time, a still kept its initial value when accessing the index 0, so 1 is printed. The second snippet is equivalent to :
int val = b[3];
System.out.println(a[val]);
a =b;
Upvotes: 0
Reputation: 43728
The relevant part of the Java Language specification (15.13.1. Run-Time Evaluation of Array Access) states:
An array access expression is evaluated using the following procedure: First, the array reference expression is evaluated. If this evaluation completes abruptly, then the array access completes abruptly for the same reason and the index expression is not evaluated. Otherwise, the index expression is evaluated. If this evaluation completes abruptly, then the array access completes abruptly for the same reason.
The first snippet is the easy part: after the statement int val = (a = b)[3];
the array variable a
points to the array { 2, 3, 1, 0 }
taking the element at index 0 gives the answer 2.
In the second snippet the a
is evaluated before the index expression, so a
points to the array { 1, 2, 3, 4 }
. Taking the element at index 0 this time gives the answer 1.
Upvotes: 1
Reputation: 20608
In the first code snippet the interesting part is
int val = (a = b)[3]
Here there are two assignments. The first one (a = b
) will happen first and lets the variable a
also reference the array that b
refers to (note that the old array is not referenced anymore and thus is eligible to being garbage collected).
Afterwards you ask for the element on index 3. And that is the value "0". The output then asks for the element on index 0 in that array. And as you can see, this is the value "2". Remember that a
now refers to the same array as b
.
In the second code snippet you are doing all in the same line:
System.out.println(a[val = ((a = b)[3])]);
Although the assignments and indexing look the same, the major difference here is that you are accessing the array (referenced by a
) before you reassign the variable.
So after all assignments are done, the variable val
has the same value "0" and the variable a
refers to the same array as b
. But now the first element (index 0) in the old array will be looked up. And that is "1".
Upvotes: 1
Reputation: 5414
there is two set of experssions:
A:
1. int val = (a = b)[3];
2. a [val]
and B:
1. a[val = ((a = b)[3])]
after executing A.1: a={2,3,1,0}
and val=0
so a[val]=2
when executing B.1: a={1,2,3,4}
and val=0
so a[val]=1
in B
the (a=b)
is a reference to {2,3,1,0}
so (a=b)[3]=0
and val=0
and a
is a reference to {1,2,3,4}
(because the assignment does not complete yet) so a[0]=1
Upvotes: 0
Reputation: 1499760
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.
Upvotes: 2