Let me say this very clearly, because people do not understand this all the time:
The procedure for calculating subexpressions is independent of associativity and priority . Associativity and priority determine in which order the statements are executed, but do not determine in which order the subexpressions are calculated. Your question is about the order in which subexpressions are evaluated.
Consider A() + B() + C() * D() . Multiplication has a higher priority than addition, and addition is left-associative, so this is equivalent to (A() + B()) + (C() * D()) but knowing that it only says that the first will happen addition to the second addition, and that multiplication will occur before the second addition. He does not tell you in what order A (), B (), C () and D () will be called! (He also does not tell you whether multiplication occurs before or after the first addition.) It would be entirely possible to obey the rules of seniority and associativity by compiling it as follows:
d = D()
Here all the rules of priority and associativity are observed - the first addition occurs before the second addition, and multiplication occurs before the second addition. It is clear that we can make calls A (), B (), C () and D () in any order and at the same time follow the rules of seniority and associativity!
We need a rule that is not related to the rules of priority and associativity to explain the order in which subexpressions are evaluated. Corresponding rule in Java (and C #): "subexpressions are evaluated from left to right." Since A () is displayed to the left of C (), A () is calculated first, regardless of the fact that C () is involved in the multiplication, and A () is involved only in addition.
So now you have enough information to answer your question. In a[b] = b = 0 , the associativity rules say that it is a[b] = (b = 0); but this does not mean that b=0 started first! Priority rules say that indexing takes precedence over assignment, but this does not mean that the indexer works before the rightmost assignment .
(UPDATE: an earlier version of this answer had some small and almost unimportant omissions in the next section, which I fixed. I also wrote a blog article describing why these rules are reasonable in Java and C # here: https://ericlippert.com / 2019/01/18 / indexer-error-cases / )
Priority and associativity only tells us that assigning zero to b must occur before assigning a[b] , because assigning zero calculates the value assigned in the indexing operation. Priority and associativity alone do not say anything about whether a[b] is evaluated before or after b=0 .
Again, this is the same as: A()[B()] = C() - all we know is that indexing must be done before assignment. We do not know whether A (), B (), or C () is executed primarily on the basis of priority and associativity. We need another rule to tell us this.
The rule, again, is "when you have a choice of what to do first, always go from left to right." However, there is an interesting crease in this particular scenario. Is a side effect of a thrown exception caused by a collection of zero or an index outside the valid range considered to be part of the calculation of the left side of the destination, or part of the calculation of the destination itself? Java chooses the latter. (Of course, this difference only matters if the code is already incorrect, because the correct code does not dereference zero and does not pass a bad index in the first place.)
So what is going on?
- A
a[b] is to the left of b=0 , so a[b] is first run, which leads to a[1] . However, validation of this indexing operation is delayed. - Then
b=0 occurs. - Then, a check is made that
a is valid and a[1] is in the range - The assignment of the value of
a[1] occurs last.
Thus, although in this particular case there are some subtleties that should be taken into account for those rare cases of errors that should not primarily occur in the correct code, in the general case you can reason: things on the left happen earlier than things on the right . This is the rule you are looking for. Talking about seniority and associativity is confusing and inappropriate.
People are always mistaken, even those who need to know better. I have edited too many programming books in which the rules were incorrectly formulated, so it is not surprising that many people have completely incorrect ideas about the relationship between priority / associativity and the order of evaluation, namely that in reality there are no such relations; they are independent.
If this topic interests you, see My articles on this topic for further reading:
http://blogs.msdn.com/b/ericlippert/archive/tags/precedence/
They are about C #, but most of these things apply equally well to Java.