Оператор присваивания в Java - Вопросы

Всего: 2 вопросов

1. 

Как устроен оператор присваивания = в Java и какая у него ассоциативность?

Синтаксис: переменная = выражение; — сначала вычисляется правая часть (выражение), затем её значение записывается в переменную слева. Слева обязана стоять изменяемая переменная (l-value), справа — любое выражение совместимого типа.

Оператор = право-ассоциативен: в цепочке a = b = c = 5 он группируется как a = (b = (c = 5)) и выполняется справа налево. При этом само присваивание — это выражение, значением которого является присвоенное значение, поэтому цепочки и работают.

2. 

Почему b += 5; компилируется, а b = b + 5; — нет, если b имеет тип byte?

byte b = 10;
b += 5;      // компилируется
b = b + 5;   // ошибка компиляции

Дело в неочевидной детали составных операторов присваивания (JLS 15.26.2). Запись E1 op= E2 НЕ эквивалентна E1 = E1 op E2 буквально — на самом деле она равна E1 = (T)((E1) op (E2)), где T — тип левой части. То есть в += уже встроен неявный сужающий каст к типу переменной.

Поэтому b += 5; означает b = (byte)(b + 5); и компилируется без проблем. А в обычном присваивании b = b + 5; такого каста нет: при вычислении b + 5 оба операнда промоутятся до int, и результат типа int нельзя присвоить в byte без явного приведения. Чтобы этот вариант скомпилировался, нужно написать b = (byte)(b + 5);.

Тот же скрытый каст в +=, -=, *= и т.д. может молча обрезать значение при переполнении — об этом легко забыть.

Страница 1 из 1