Интересно, есть ли что-нибудь в спецификации Java, которая точно определяет поведение этого. (Очевидно, это утверждение означает, что мне лень проверять.)
Обратите внимание, из байт-кода Тома, ключевые строки - 7, 8 и 11. Строка 7 загружает x в стек вычислений. Строка 8 увеличивает x. Строка 11 сохраняет значение из стека обратно в x. В обычных случаях, когда вы не присваиваете значения обратно самим себе, я не думаю, что была бы какая-либо причина, по которой вы не могли бы загрузить, сохранить, затем увеличить. Вы получите тот же результат.
Например, предположим, у вас был более нормальный случай, когда вы написали что-то вроде:
г = (х ++) + (у ++);
Будь то сказано (псевдокод, чтобы пропустить технические детали)
load x
increment x
add y
increment y
store x+y to z
или
load x
add y
store x+y to z
increment x
increment y
не имеет значения. Я думаю, что любая реализация должна быть действительной.
Я бы очень осторожно относился к написанию кода, который зависит от этого поведения. Это выглядит очень зависящим от реализации, между трещинами в спецификациях для меня. Единственный раз, когда это будет иметь значение, если вы сделали что-то сумасшедшее, например, приведенный здесь пример, или если у вас было запущено два потока и вы зависели от порядка вычисления в выражении.