Переназначение примитивной переменной Java во время выражения

У меня был вопрос в моем тесте, который меня запутал (код прикреплен ниже). Короче говоря, я думал, что переменные переназначаются, а затем добавляются обратно в качестве значения выражения (делая вывод 8, 10), но похоже, что исходное значение почему-то не изменилось. Что мне не хватает?

p.s. Извините, если подобный вопрос существует, я не смог его найти (возможно, это слишком очевидно: P).

class InitTest{
    public static void main(String[] args){
        int a = 10;
        int b = 20;
        a += (a = 4);
        b = b + (b = 5);
        System.out.println(a + ",  " + b);
    }
}

person Artur Shalimov    schedule 02.09.2020    source источник
comment
Пожалуйста, не пишите такой код — как вы, наверное, заметили, сложно понять, что он на самом деле делает.   -  person    schedule 02.09.2020
comment
@Taschi: такой плохой код, вероятно, является краеугольным камнем сертификационных экзаменов по программированию.   -  person Hovercraft Full Of Eels    schedule 02.09.2020
comment
@HovercraftFullOfEels, я не являюсь сертифицированным разработчиком Java, но если сертификационные экзамены действительно учат людей полагаться на пограничные случаи, то еще более необходимо указать, что это плохой код.   -  person    schedule 02.09.2020
comment
@Taschi-corporationsarebad Это не мой код????. Это был пример, и мне нужно было выбрать ответ.   -  person Artur Shalimov    schedule 02.09.2020


Ответы (2)


a += (a = 4);

Сказанное выше логически эквивалентно следующему:

a = a + (a = 4);

Если мы заменим существующее значение на a, это упростится до:

a = 10 + 4 = 14

Мы можем сделать то же самое для b:

b = b + (b = 5) = 20 + 5 = 25

Мы видим этот результат из-за приоритета оператора. Оператор сложения + имеет более высокий приоритет, чем оператор присваивания =, как определено в Java таблица приоритетов операторов.

Вы можете видеть, что оператор сложения-присваивания += имеет тот же приоритет, что и оператор присваивания, и в этом случае выражение вычисляется слева направо.


Если бы вместо этого были выражения:

a = (a = 4) + a;
b = (b = 5) + b;

Тогда это приведет к ожидаемому результату (a = 8, b = 10), так как левый операнд вычисляется перед правым операндом (при вычислении выражения). Я попытаюсь найти, где это указано в спецификации языка Java.

person Jacob G.    schedule 02.09.2020
comment
Оооо, теперь понял. Моя ошибка заключалась в том, что я предполагал, что значение будет динамически меняться - person Artur Shalimov; 02.09.2020
comment
Выражения оцениваются в соответствии с приоритетом оператора. Слева направо оцениваются операнды. Результаты OP обусловлены приоритетом оператора. - person user207421; 02.09.2020
comment
@JacobG.Значит, в этом случае круглые скобки считаются не арифметическими, а просто разделителями для присваивания? (я думал, что скобки имеют более высокий OP) - person Artur Shalimov; 02.09.2020
comment
@ArturShalimov Для получения дополнительной информации о роли скобок в оценке выражений я бы посмотрел здесь: Если скобки имеют более высокий приоритет, то почему увеличивается оператор решен первым? - person Jacob G.; 02.09.2020

В Java при присвоении значения переменной первой вычисляется левая часть знака =, а затем правая. Поэтому, когда вы пишете a += (a = 4);, что эквивалентно a = a + (a=4), что совпадает с a = a + 4, то же самое для b.

person Kostas Konnidis    schedule 02.09.2020
comment
Зачем вычислять левую часть знака =? Это просто идентификатор. Вы не можете назначить что-то a + 5. - person ; 02.09.2020
comment
@Taschi-corporationsarebad Левая сторона должна быть преобразована в переменную, которая может быть полем объекта или компонентом массива; например, getObj().getArray()[4] = 5, очевидно, должен вызывать два метода. Левая часть оценивается раньше, чем правая. - person kaya3; 02.09.2020
comment
@ kaya3, достаточно справедливо, но оценка - это не то же самое, что расчет. Мой пример a + 5 не является допустимой левой частью для присваивания. - person ; 02.09.2020
comment
Является ли вычисление вычислением или нет, на самом деле не определяется в техническом смысле. Но если он должен выполнять арифметические действия с числами для подсчета, то foo(a + 5).bar = "baz"; должен соответствовать вашему критерию. - person kaya3; 02.09.2020