Почему x == (x = y) не совпадает с (x = y) == x? - PullRequest
0 голосов
/ 12 декабря 2018

Рассмотрим следующий пример:

class Quirky {
    public static void main(String[] args) {
        int x = 1;
        int y = 3;

        System.out.println(x == (x = y)); // false
        x = 1; // reset
        System.out.println((x = y) == x); // true
     }
}

Я не уверен, есть ли элемент в спецификации языка Java, который диктует загрузку предыдущего значения переменной для сравнения с правой стороной (x = y) который в порядке, указанном в скобках, должен быть рассчитан первым.

Почему первое выражение оценивается как false, а второе - true?Я ожидал, что сначала будет оцениваться (x = y), а затем он сравнил бы x с самим собой (3) и вернул бы true.


Этот вопрос отличается от порядок вычисления подвыражений в Java-выражении в том смысле, что x здесь определенно не является «подвыражением».Для сравнения он должен быть загружен , а не «оценен».Вопрос специфичен для Java, и выражение x == (x = y), в отличие от надуманных непрактичных конструкций, обычно создаваемых для сложных вопросов интервью, пришло из реального проекта.Предполагалось, что это будет однострочная замена для идиомы сравнения и замены

int oldX = x;
x = y;
return oldX == y;

, которая, будучи даже более простой, чем инструкция x86 CMPXCHG, заслуживает более короткого выражения в Java.

Ответы [ 14 ]

0 голосов
/ 13 декабря 2018

, который в порядке, указанном в скобках, должен быть рассчитан первым

Нет.Это распространенное заблуждение, что круглые скобки оказывают (общее) влияние на порядок расчета или оценки.Они только приводят части вашего выражения в определенное дерево, связывая правильные операнды с правильными операциями для задания.

(И, если вы их не используете, эта информация поступает из «приоритета»)и ассоциативность операторов, что является результатом того, как определяется синтаксическое дерево языка. На самом деле, это все еще именно так, как это работает, когда вы используете скобки, но мы упрощаем и говорим, что тогда мы не полагаемся ни на какие правила предшествования.)

Как только это будет сделано (т.е. когда ваш код будет проанализирован в программе), эти операнды все еще должны быть оценены, и существуют отдельные правила о том, как это делается: упомянутые правила (как показал нам Эндрю).) утверждают, что LHS каждой операции сначала оценивается в Java.

Обратите внимание, что это не так во всех языках;например, в C ++, если вы не используете оператор короткого замыкания, такой как && или ||, порядок вычисления операндов обычно не определен, и вы не должны полагаться на него в любом случае.

Учителя должны прекратить объяснять приоритет оператора, используя вводящие в заблуждение фразы, такие как «это делает сложение первым».С учетом выражения x * y + z правильное объяснение будет следующим: «приоритет оператора заставляет сложение происходить между x * y и z, а не между y и z», без упоминания какого-либо «порядка».

0 голосов
/ 13 декабря 2018

В первом тесте, который вы проверяете, 1 == 3.

Во втором тесте, который вы проверяете, 3 == 3.

(x = y) присваивает значение иэто значение проверяется.В первом примере сначала x = 1, затем присваивается x 3. 1 == 3?

В последнем случае х назначается 3, и, очевидно, это все еще 3. 3 == 3?

0 голосов
/ 12 декабря 2018

== является двоичным оператором равенства .

Левый операнд бинарного оператора представляется полностью вычисленным перед оценивается любая часть правого операнда .

Спецификация Java 11> Порядок оценки> Сначала выполняется оценка левого операнда

0 голосов
/ 12 декабря 2018

Как сказал Луи Вассерман, выражение оценивается слева направо.И java не заботится о том, что на самом деле делает «define», он заботится только о том, чтобы сгенерировать (энергонезависимое, окончательное) значение для работы.

//the example values
x = 1;
y = 3;

Итак, чтобы вычислить первый вывод System.out.println(),делается следующее:

x == (x = y)
1 == (x = y)
1 == (x = 3) //assign 3 to x, returns 3
1 == 3
false

и для вычисления второго:

(x = y) == x
(x = 3) == x //assign 3 to x, returns 3
3 == x
3 == 3
true

Обратите внимание, что второе значение всегда будет иметь значение true, независимо от начальных значений x иy, потому что вы эффективно сравниваете присвоение значения переменной, которой оно назначено, и a = b и b, оцененные в этом порядке, всегда будут одинаковыми по определению.

...