Операторы Java ·
‹ Предыдущий Следующий ›
⏱ 5 минут чтения Обновлено: 2026-07-11

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

Оператор присваивания = — самый используемый оператор Java: он сохраняет значение выражения в переменной. При этом присваивание в Java — не просто команда, а выражение, которое само имеет значение. Из этого свойства вытекают и цепочки вида x = y = z = 100, и популярные идиомы наподобие чтения файла в цикле while.

Синтаксис оператора присваивания

Общая форма оператора присваивания в языке Java:

переменная = выражение;

Сначала полностью вычисляется выражение справа, затем результат записывается в переменную слева. Слева всегда стоит переменная (или элемент массива, поле объекта) — записать 10 = x; нельзя, это ошибка компиляции.

Переменная и выражение должны иметь совместимый тип. В int можно присвоить значение byte или short (расширение выполняется автоматически), а вот присвоить long в int без явного приведения типа компилятор не позволит:

int i = 100;
long l = i;      // OK: расширяющее преобразование int -> long
// int k = l;    // Ошибка компиляции: требуется приведение (int) l

Помимо простого =, в Java есть целое семейство составных операторов присваивания+=, -=, *=, /=, %= и другие, объединяющих арифметическую или битовую операцию с присваиванием. Это отдельная большая тема; их логические разновидности &=, |=, ^= разобраны в уроке о логических операторах.

Цепочки присваиваний и порядок вычисления

Так как присваивание возвращает значение, присваивания можно объединять в цепочки — это удобный способ инициализировать несколько переменных одним значением:

int x, y, z;
x = y = z = 100; // всем трём переменным присвоено значение 100

Оператор = правоассоциативен, поэтому цепочка вычисляется справа налево: x = (y = (z = 100)). Сначала z получает 100; значением выражения z = 100 является 100, и оно присваивается y; наконец значение выражения y = ... присваивается x.

Важно

Цепочка x = y = z = 100 выполняется справа налево: сначала z = 100, потом y = z, потом x = y. Именно поэтому все переменные в цепочке, кроме самой правой части, обязаны быть уже объявлены, а их типы — совместимы со значением справа.

Обратите внимание: цепочка работает только для присваивания. Объявить несколько переменных с инициализацией одной строкой вида int a = b = 5; нельзя, если b ещё не объявлена, — в объявлении каждая переменная инициализируется отдельно.

Присваивание как выражение

Выражение переменная = значение само имеет значение — то, которое было присвоено. Поэтому присваивание можно использовать внутри другого выражения:

int a;
int b = (a = 5) + 10; // a = 5, b = 15

Классическое практическое применение — чтение данных в цикле, когда присваивание и проверка результата совмещены в одном условии:

String line;
while ((line = reader.readLine()) != null) { // читаем, пока есть строки
    System.out.println(line);
}

Скобки вокруг line = reader.readLine() обязательны: у != приоритет выше, чем у =, и без скобок компилятор попытался бы присвоить line результат сравнения.

У этой гибкости есть обратная сторона, на которой часто ошибаются новички: перепутанные = и ==. С числами такой код не скомпилируется, но с boolean — вполне:

boolean flag = false;
if (flag = true) { // ПРИСВАИВАНИЕ, а не сравнение! Условие всегда true
    System.out.println("Выполнится всегда");
}

Здесь вместо оператора сравнения == написан оператор присваивания: flag получает значение true, оно же становится значением всего выражения, и ветка выполняется всегда. Для boolean-переменных безопаснее писать просто if (flag) или if (!flag) — тогда опечатка невозможна.

Примитивы и ссылки: что на самом деле копируется

Оператор = всегда копирует значение, хранящееся в переменной. Для примитивных типов это само число или логическое значение, а для ссылочных типов — ссылка на объект, а не сам объект:

Тип переменной Что копируется при b = a Связаны ли переменные после присваивания
Примитив (int, double, boolean…) Само значение Нет: изменение b не влияет на a
Ссылочный тип (объект, массив, String…) Ссылка на объект Да: обе переменные указывают на один объект

С примитивами всё интуитивно — копия независима:

int a = 10;
int b = a; // b получает копию значения
b = 20;
System.out.println(a); // 10 - переменная a не изменилась

Со ссылочными типами картина другая: после присваивания обе переменные указывают на один и тот же объект, и изменение объекта через одну переменную видно через другую:

StringBuilder sb1 = new StringBuilder("Java");
StringBuilder sb2 = sb1;   // копируется ссылка, объект один
sb2.append(" 21");
System.out.println(sb1);   // Java 21 - изменение видно через sb1!

Важно

Присваивание ссылочных типов никогда не копирует объект — только ссылку на него. Если нужна независимая копия объекта или массива, её создают явно: конструктором копирования, методом clone(), Arrays.copyOf() и т. п. Само же присваивание одинаково дёшево для любого типа.

Часто задаваемые вопросы

В каком порядке выполняется цепочка x = y = z = 100?

Справа налево: оператор присваивания правоассоциативен, поэтому запись эквивалентна x = (y = (z = 100)). Сначала z получает 100, затем значение выражения z = 100 присваивается y, и в конце — x. В итоге все три переменные равны 100.

Чем оператор = отличается от ==?

Одиночный = — присваивание: он записывает значение в переменную. Двойной == — сравнение на равенство, возвращающее boolean. Опечатка if (flag = true) с boolean-переменной компилируется и делает условие всегда истинным, поэтому для логических переменных пишите if (flag) без сравнения.

Копируется ли объект при присваивании одной переменной другой?

Нет. Для ссылочных типов оператор = копирует только ссылку, и обе переменные начинают указывать на один и тот же объект: изменение объекта через одну переменную видно через другую. Чтобы получить независимую копию, объект нужно копировать явно — например, конструктором копирования или Arrays.copyOf() для массивов.

Можно ли использовать присваивание внутри условия или другого выражения?

Да: присваивание в Java — выражение, значением которого является присвоенное значение. На этом основан приём чтения в цикле: while ((line = reader.readLine()) != null). Скобки вокруг присваивания обязательны, так как приоритет = ниже, чем у сравнения. Злоупотреблять приёмом не стоит — он снижает читаемость.

Презентацию с видео можно скачать на Patreon.

Видео объяснение

Предпочитаете видеоформат? Посмотрите этот урок с примерами и объяснениями.

Комментарии

Зарегистрируйтесь или войдите, чтобы иметь возможность оставить комментарий.