Question on associativity and precedence

A

ankur

int[] z = {10,20,30,40,50};
int index = 4;
z[index] = index = 2;

System.out.println(z[0]);
System.out.println(z[1]);
System.out.println(z[2]);
System.out.println(z[3]);
System.out.println(z[4]);



This code gives

10
20
30
40
2

Why does it not give:
10
20
2
40
50

Why z[2] is not assigned 2?? How can this be explained in terms of
associativity and precedence rules.
 
M

Mark Space

ankur said:
Why z[2] is not assigned 2?? How can this be explained in terms of
associativity and precedence rules.

Good question. I think this is the answer:

<http://java.sun.com/docs/books/jls/third_edition/html/expressions.html#15.26.1>

"If the left-hand operand is an array access expression ... then:

* First, the array reference subexpression of the left-hand operand
array access expression is evaluated.... "


So that's the order because the JLS says it is.

For assignment, a = (b = c); if "a" is an expression (?, I think
"expression" is correct, the same section talks about fields too) a is
evaluated first. Then "(b = c)" is evaluated. I'd assume that if "b"
is an expression, it will be evaluated before "c". I'd have to look-up
which one of those is precedence, and which is associativity. It may be
both one or the other, too, I suppose.

Finally, the assignments occur.
 
J

Joshua Cranmer

ankur said:
int[] z = {10,20,30,40,50};
int index = 4;
z[index] = index = 2;

Generated bytecode (roughly):

iconst_4 push 4 on to the stack
istore <index> store the top of the stack (4) into index
aload <z> load z to the stack
iload <index> load index (4) on the stack
iconst_2 push 2 on to the stack
dup duplicate the top element (2) on the stack
istore <index> store the top of the stack (2) into index
iastore store the top of the stack into the index denoted by the
second value on the stack of the array denoted by the
third item of the stack.

In general, an operand is resolved before any of the operands to the
right of it and after any operand to its left, such that an assignment
to its right does not affect any usages of the variable to its left.
Left and right are defined, of course, in terms of the JLS and are more
properly before and after, but human notation makes left/right clearer.
 
J

Joshua Cranmer

Roedy said:
z[index] = index = 2;

first of all, don't use cascaded assignment operators. The only time
you see them in on exams.

Not quite true: I occasionally use something in the form of "x = y = 0"
myself, but it tends to be rare.

Certainly, it's not at as stupid as the ageless C question "What does
i=i++ evaluate to?"
 
M

Mark Space

Reading the JLS a bit more, I found this:

<http://java.sun.com/docs/books/jls/third_edition/html/expressions.html#15.26.1>

"Otherwise, three steps are required:

* First, the left-hand operand is evaluated to produce a variable.
If this evaluation completes abruptly, then the assignment expression
completes abruptly for the same reason; the right-hand operand is not
evaluated and no assignment occurs.
* Otherwise, the right-hand operand is evaluated. If this
evaluation completes abruptly, then the assignment expression completes
abruptly for the same reason and no assignment occurs. "

"Otherwise" means if the left hand operand of an assignment is neither a
field or an array.

But the point is the operand is evaluated "first to produce a variable."
This is implies to me that there are two passes over a Java
expression. First, to produce variables. This pass seems to go left to
right. (I can't think of a case where grouping or precedence would make
it go differently.)

Then in the second pass the variables are evaluated with the specified
order of operations. All expressions are evaluated here.

The exception in both cases seems to be the short circuit operators,
which may not evaluate their right hand variables or operations at all,
depending on the value of the left hand expression.

To me, that latter bit implies that expressions involving || and &&
might evaluate differently than the OP's example.


Getting back on track a bit:

Joshua said:
> Generated bytecode (roughly):
>
> iconst_4 push 4 on to the stack
> istore <index> store the top of the stack (4) into index
> aload <z> load z to the stack
> iload <index> load index (4) on the stack
> iconst_2 push 2 on to the stack
> dup duplicate the top element (2) on the stack
> istore <index> store the top of the stack (2) into index
> iastore store the top of the stack into the index denoted by

I think the compiler could choose to evaluate "aload <z>" in a different
order of the JLS were different. Get rid of the iconst_4 and move the
evaluation of aload <z> down a bit and you get the effect the OP seems
to be expecting. It's even one less byte code, I think. The compiler
is doing extra work to conform to the JLS.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,054
Latest member
TrimKetoBoost

Latest Threads

Top