Позвольте мне сказать это очень четко, потому что люди все время неправильно понимают это:
Порядок оценки подвыражений является независимым как ассоциативности, так и приоритета. Ассоциативность и приоритет определяют, в каком порядке выполняются операторы , но не определяют, в каком порядке оцениваются подвыражения . Ваш вопрос касается порядка, в котором оцениваются подвыражения .
Рассмотрим A() + B() + C() * D()
. Умножение имеет более высокий приоритет, чем добавление, а добавление лево-ассоциативное, поэтому это эквивалентно (A() + B()) + (C() * D())
. Но зная, что только говорит вам, что первое добавление произойдет до второго добавления и что умножение произойдет до второго добавления. Он не говорит вам, в каком порядке будем называть A (), B (), C () и D ()! (Он также не говорит вам, происходит ли умножение до или после первого добавления.) Было бы вполне возможно подчиняться правилам приоритета и ассоциативности , компилируя это как:
d = D() // these four computations can happen in any order
b = B()
c = C()
a = A()
sum = a + b // these two computations can happen in any order
product = c * d
result = sum + product // this has to happen last
Все правила приоритета и ассоциативности следуют туда - первое дополнение происходит до второго добавления, а умножение происходит до второго добавления. Ясно, что мы можем выполнять вызовы A (), B (), C () и D () в любом порядке и по-прежнему подчиняться правилам приоритетности и ассоциативности!
Мы требуется правило , не связанное с правилами приоритета и ассоциативности, чтобы объяснить порядок, в котором оцениваются подвыражения. Соответствующим правилом в Java (и C #) является «подвыражения оцениваются слева направо». Так как A () появляется слева от C (), сначала оценивается A (), независимо от того, что C () участвует в умножении, а A () участвует только в добавлении.
Итак, теперь у вас достаточно информации, чтобы ответить на ваш вопрос. В a[b] = b = 0
правила ассоциативности говорят, что это a[b] = (b = 0);
, но это не значит, что b=0
работает первым! В правилах приоритета говорят, что индексирование имеет более высокий приоритет, чем присвоение, но это не означает, что индексатор работает до самого правого присваивания.
Правила приоритета и ассоциативности налагают ограничения, которые:
Приоритет и ассоциативность говорят только о том, что присвоение нулю до b
должно происходить до присвоения a[b]
, Приоритет и ассоциативность ничего не говорят о том, оценивается ли a[b]
до или после b=0
.
Опять же, это то же самое, что: A()[B()] = C()
- Все, что мы знаем, это то, что индексирование должно произойти до назначения. Мы не знаем, выполняется ли сначала A (), B () или C () на основе приоритета и ассоциативности . Нам нужно другое правило, чтобы сказать нам это.
Правило опять же «когда у вас есть выбор, что делать сначала, всегда идите влево-вправо»: a[b]
находится слева от b=0
, поэтому a[b]
сначала запускает , в результате получается a[1]
. Затем происходит b=0
, а затем присваивание значения a[1]
происходит последним.
Вещи слева случаются перед вещами справа. Это правило, которое вы ищете. Разговоры о приоритетности и ассоциативности оба сбивают с толку и неактуальны.
Люди все время ошибаются , даже люди, которые должны знать лучше. Я отредактировал слишком много книг по программированию, которые неправильно указали правила, поэтому неудивительно, что многие люди имеют совершенно неверные убеждения относительно взаимосвязи между приоритетом / ассоциативностью и порядком оценки, а именно, что в действительности нет таких отношений; они независимы.
Если эта тема вас интересует, см. мои статьи по этому вопросу для дальнейшего чтения:
http://blogs.msdn.com/b/ericlippert / archive / tags / priority /
Они относятся к C #, но большая часть этого материала одинаково хорошо применима к Java.