Я не уверен, есть ли элемент в спецификации языка Java, который диктует загрузку предыдущего значения переменной ...
Там есть. В следующий раз, когда вам непонятно, что говорится в спецификации, прочитайте ее, а затем задайте вопрос, если она неясна.
... правая часть, (x = y)
которая в порядке, указанном в скобках, должна быть рассчитана первой.
Это утверждение является ложным. Скобки не подразумевают порядок оценки . В Java порядок вычисления слева направо, независимо от круглых скобок. Скобки определяют, где находятся границы подвыражения, а не порядок оценки.
Почему первое выражение оценивается как ложное, а второе - как истинное?
Правило для ==
оператора: оценить левую сторону для получения значения, оценить правую сторону для получения значения, сравнить значения, сравнение - это значение выражения.
Другими словами, значение expr1 == expr2
всегда такое же, как если бы вы написали, temp1 = expr1; temp2 = expr2;
а затем оценили temp1 == temp2
.
Правило для =
оператора с локальной переменной слева: вычисление левой стороны для создания переменной, вычисление правой стороны для получения значения, выполнение присваивания, результатом является присвоенное значение.
Итак, соберите это вместе:
x == (x = y)
У нас есть оператор сравнения. Оцените левую сторону, чтобы получить значение - мы получим текущее значение x
. Оцените правую сторону: это присваивание, поэтому мы оцениваем левую сторону для создания переменной - переменной x
- мы оцениваем правую сторону - текущее значение y
- присваиваем ее x
, а результатом является присвоенное значение. Затем мы сравниваем исходное значение x
со значением, которое было присвоено.
Вы можете сделать (x = y) == x
в качестве упражнения. Опять же, помните, что все правила оценки левой стороны предшествуют всем правилам оценки правой стороны .
Я ожидал, что (x = y) будет сначала оценен, а затем он сравнил бы x с самим собой (3) и вернул бы true.
Ваше ожидание основано на ряде неверных представлений о правилах Java. Надеюсь, теперь у вас есть правильные убеждения и вы будете ожидать в будущем истинных вещей.
Этот вопрос отличается от «порядка вычисления подвыражений в выражении Java»
Это утверждение неверно. Этот вопрос совершенно уместен.
x здесь определенно не является «подвыражением».
Это утверждение также ложно. Это подвыражение дважды в каждом примере.
Его нужно загружать для сравнения, а не «оценивать».
Я без понятия что это значит.
Видимо у тебя еще много ложных убеждений. Мой совет, чтобы вы читали спецификацию, пока ваши ложные убеждения не будут заменены истинными убеждениями.
Вопрос специфичен для Java, и выражение x == (x = y), в отличие от надуманных непрактичных конструкций, обычно создаваемых для сложных вопросов интервью, пришло из реального проекта.
Происхождение выражения не имеет отношения к вопросу. Правила для таких выражений четко описаны в спецификации; прочитай это!
Предполагалось, что это будет замена одной строки для сравнения и замены
Поскольку эта однострочная замена вызывала у вас, читателя кода, большую путаницу, я бы сказал, что это был неудачный выбор. Делать код более кратким, но более сложным для понимания - не победа. Вряд ли код станет быстрее.
Кстати, в C # есть метод сравнения и замены в виде библиотечного метода, который можно сопоставить с машинной инструкцией. Я полагаю, что у Java нет такого метода, поскольку он не может быть представлен в системе типов Java.