Операторы присваивания в Java
Присваивайте значения переменным с помощью =, +=, -=, *=, /=, %= и составных побитовых операторов присваивания.
Одиночный = — это базовый оператор присваивания. Java также предоставляет семейство составных операторов присваивания, которые объединяют арифметическую, побитовую операцию или операцию сдвига с самим присваиванием. Они сокращают код и делают намерение — «изменить эту переменную на месте» — более понятным.
Простое присваивание
Правая часть вычисляется, а затем сохраняется в переменную в левой части:
int x = 5;
int y = x + 3;
y = y * 2;
System.out.println(y); // 16Несколько правил:
- Левая часть должна быть переменной (или элементом массива, или полем), но не выражением вроде
(x + 1) = 5. - Типы должны совпадать — или правая часть должна быть неявно приводима к типу левой части.
- Присваивание само по себе является выражением:
int a = (b = 5);устанавливает иa, иbв значение5.
Составные операторы присваивания
Каждый арифметический и побитовый оператор имеет парный составной оператор присваивания:
| Оператор | Полная форма |
|---|---|
+= | x = x + value |
-= | x = x - value |
*= | x = x * value |
/= | x = x / value |
%= | x = x % value |
&= | x = x & value |
| ` | =` |
^= | x = x ^ value |
<<= | x = x << value |
>>= | x = x >> value |
>>>= | x = x >>> value |
На практике:
int total = 0;
total += 5; // total = 5
total += 3; // total = 8
total *= 2; // total = 16
total -= 1; // total = 15
total /= 3; // total = 5Побитовые операторы и операторы сдвига работают так же — они применяют операцию к текущему значению переменной и сохраняют результат обратно:
int flags = 0b0101; // 5
flags |= 0b0010; // set a bit -> 0b0111 = 7
flags &= 0b0110; // clear bits -> 0b0110 = 6
flags <<= 1; // shift left -> 0b1100 = 12Правая часть группируется целиком
x op= y — это не слепая текстовая подстановка x = x op y. Компилятор рассматривает всю правую часть как один операнд, как если бы она была в скобках — x = x op (y):
int x = 10;
x *= 2 + 3; // x = x * (2 + 3) = 50, NOT x = x * 2 + 3 = 23
System.out.println(x); // 50+= со строками
+= также выполняет конкатенацию строк:
String greeting = "Hello";
greeting += ", world!"; // "Hello, world!"Каждый += для String создаёт новую строку под капотом — строки неизменяемы. Для циклов, которые формируют длинную строку, используйте StringBuilder (рассматривается в Java String Concatenation).
Составное присваивание включает неявное приведение типов
Тонкая, но важная особенность: составные операторы присваивания включают неявное приведение обратно к типу переменной. Простое присваивание этого не делает.
byte b = 10;
// b = b + 1; // compile error: int can't fit into byte without a cast
b += 1; // OK — compound form casts implicitly
System.out.println(b); // 11Это иногда полезно — и иногда является скрытой ловушкой, если прячет переполнение.
Присваивание является выражением — но не злоупотребляйте этим
Поскольку присваивание возвращает значение, его можно выстраивать в цепочку:
int a, b, c;
a = b = c = 10; // all three set to 10Можно также выполнять присваивание внутри условия if:
String line;
while ((line = reader.readLine()) != null) {
process(line);
}Эти идиомы распространены в циклах ввода-вывода. За пределами конструкции while ((x = ...) != null) предпочитайте отдельные операторы — их легче читать.
= против ==
Самый распространённый источник ошибок, возникающих из-за одного символа в Java, — путаница между = (присваивание) и == (сравнение):
int x = 5;
// if (x = 10) { ... } // compile error: int is not a boolean
// if (x == 10) { ... } // OKДля int и большинства типов компилятор немедленно обнаруживает ошибку, потому что = возвращает int, а не boolean. С переменными типа boolean ошибки компиляции нет — присваивание с = всегда возвращает присвоенное boolean-значение — поэтому будьте особенно осторожны при проверке флагов:
boolean isOpen = false;
if (isOpen = true) { ... } // bug: this sets isOpen and is always true
if (isOpen == true) { ... } // works, but...
if (isOpen) { ... } // ...this is what you actually wantДемонстрация
Что дальше
Java Comparison Operators охватывает ==, !=, операторы отношения и принципиальное различие между == и .equals() для объектов.