• Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other Pie Elite all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Campbell Ritchie
  • Tim Cooke
  • paul wheaton
  • Liutauras Vilda
  • Ron McLeod
Sheriffs:
  • Jeanne Boyarsky
  • Devaka Cooray
  • Paul Clapham
Saloon Keepers:
  • Scott Selikoff
  • Tim Holloway
  • Piet Souris
  • Mikalai Zaikin
  • Frits Walraven
Bartenders:
  • Stephan van Hulst
  • Carey Brown

array confusion

 
Ranch Hand
Posts: 143
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hi friends, please read the following code.

Output: 14
This one was bugging me for a long time, and I think I finally figured out HOW it is happening. But I still don't understand WHY it is happening. This is what is happening -
1. Both arrays a and b are declared, constructed and initialized.
2. System.out.println(a[(a=b)[3]]); //Very interesting line of code.
The inner parentheses are evaluated first i.e (a=b). Now a and b both point to the same array object ({0,1,2,3}).
3. Now the expression is (a[b[3]]) or (a[a[3]]) as a and b both point to the same object.
4. The inner array element access operator is evaluated next which results in the value 3.
5. NOW is the confusing part: The expression evaluated is (a[3]), the output is 14, which is indeed a[3], but the reference a was modified earlier to point to b. But still a points to {11,12,13,14} instead of {0,1,2,3}. WHY?
To counter-check if I had really understood HOW it is happening, I wrote the foll. code which is just a modification of the above code:

Output: 112
So, if anyone can explain WHY(not HOW) the output is 14 instead of 3 in the first example, and is 112 instead of 12 in the second example, please do so.
Thank you,
Prasanna.
 
Greenhorn
Posts: 11
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hello Prasanna,
I found this in JLS,
15.13.1 Runtime Evaluation of Array Access
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.
Otherwise, if the value of the array reference expression is null, then a NullPointerException is thrown.
Otherwise, the value of the array reference expression indeed refers to an array. If the value of the index expression is less than zero, or greater than or equal to the array's length, then an ArrayIndexOutOfBoundsException is thrown.
Otherwise, the result of the array access is the variable of type T, within the array, selected by the value of the index expression. (Note that this resulting variable, which is a component of the array, is never considered final, even if the array reference expression is a final variable.)
15.13.2 Examples: Array Access Evaluation Order
In an array access, the expression to the left of the brackets appears to be fully evaluated before any part of the expression within the brackets is evaluated. For example, in the (admittedly monstrous) expression a[(a=b)[3]], the expression a is fully evaluated before the expression (a=b)[3]; this means that the original value of a is fetched and remembered while the expression (a=b)[3] is evaluated. This array referenced by the original value of a is then subscripted by a value that is element 3 of another array (possibly the same array) that was referenced by b and is now also referenced by a.
Thus, the example:

class Test {
public static void main(String[] args) {
int[] a = { 11, 12, 13, 14 };
int[] b = { 0, 1, 2, 3 };
System.out.println(a[(a=b)[3]]);
}
}
prints:
14
because the monstrous expression's value is equivalent to a[b[3]] or a[3] or 14.
 
Prasanna Wamanacharya
Ranch Hand
Posts: 143
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Thanks a lot Nagarajan, I have understood HOW it is happening now.
Prasanna.
 
"The Hood"
Posts: 8521
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
println is a method. The parameter that println takes in is local to the method.


When the method or constructor is invoked (�15.12), the values of the actual argument expressions initialize newly created parameter variables, each of the declared Type, before execution of the body of the method or constructor.


So within the brackets of the array what we need to worry about is the order of assignment. If you have an expression, it is evaluated from left to right. If the value of one of the variables in the expression changes DURING the expression, any uses of the variable to the left of that change retain the OLD value and any uses of the variable to the right are evaluated with the NEW value.
So when evaluating (a[(a=b)[3]]); the first "a" refers to the original array, THEN the value of it is changed to point to the second array, but the JVM still remembers the first reference.
From the JLS 15.7.1 Evaluate Left-Hand Operand First


The Java programming language guarantees that the operands of operators appear to be evaluated in a specific evaluation order, namely, from left to right.
If the operator is a compound-assignment operator (�15.26.2), then evaluation of the left-hand operand includes both remembering the variable that the left-hand operand denotes and fetching and saving that variable's value for use in the implied combining operation.

 
Prasanna Wamanacharya
Ranch Hand
Posts: 143
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Cindy, thank you for the explanation. But I have a doubt here. It does not make a difference if the expression is in a method or is a simple expression. Please have a look at the foll. code.

The output is still 112.
I understood the quote from the JLS 15.7.1 Evaluate Left-Hand Operand First. It was an excellent explanation. Thanks again.
Prasanna.
 
Ranch Hand
Posts: 213
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Try the below code:
class ArrayTest {
public static void main(String [] args) {
int [] a = { 10,11,12,13,14};
int [] b = { 0,1,2,3,4,5,6,7,8,9,100,112,113,114};
int c = b[(b=a)[2]];
int d = (b=a)[2];
System.out.println("c:" + c); //prints 113
//The original b's 12 element
//is 113.
System.out.println("d:" +d); //prints 12
}
}
Let me know if that does not clear it up.
 
Prasanna Wamanacharya
Ranch Hand
Posts: 143
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Charlie, thanks for your effort, but it seems you have not read my first post clearly. All I wanted to know was WHY the expression evaluated in that manner; not HOW. I already knew HOW it was evaluating. My doubt was cleared excellently by Nagarajan and Cindy.
Thanks anyways,
Prasanna.
 
reply
    Bookmark Topic Watch Topic
  • New Topic