Вспоминаю свой первый месяц в программировании, как я смотрел на код коллеги и думал: "Что за магия с этими плюсами, минусами и странными значками типа & или ^?" Казалось, что настоящие программисты знают какой-то секретный язык. А потом понял — это просто операторы, и ничего сверхъестественного в них нет. Давай разберёмся с ними раз и навсегда.Операции над примитивными типами в Java - 1

Присваивание — твоя первая операция

Самая базовая вещь в Java — это знак =. Ты уже пользовался им сотни раз, даже не задумываясь:
int x = 5;
int y = x;
int z = x + 10;
Но вот что интересно — в Java можно делать цепочки присваивания:
int a, b, c;
a = b = c = 100;

System.out.println(a); // 100
System.out.println(b); // 100
System.out.println(c); // 100
Работает справа налево: сначала c = 100, потом b = c, и наконец a = b. Хотя если честно, такой код я встречал в реальных проектах раза три за всю карьеру. Обычно пишут попроще, чтобы коллеги не матерились при код-ревью.

Унарные операции — работают в одиночку

Унарные — значит с одним операндом. Звучит умно, но на деле всё просто.

Плюс и минус

Унарный минус меняет знак числа, а плюс... ну, ничего не делает. Серьёзно, он просто есть для симметрии:
int number = 42;
int negative = -number;
int positive = +number;

System.out.println(negative); // -42
System.out.println(positive); // 42

Инкремент и декремент — любимцы всех программистов

++ и -- — это твои лучшие друзья в циклах. Увеличивают или уменьшают значение на единицу. Но здесь есть подвох, который ловит каждого новичка. Префиксная форма — сначала изменяет, потом возвращает:
int x = 5;
int y = ++x; // сначала x становится 6, потом присваивается y

System.out.println(x); // 6
System.out.println(y); // 6
Постфиксная форма — сначала возвращает, потом изменяет:
int x = 5;
int y = x++; // сначала y получает значение 5, потом x становится 6

System.out.println(x); // 6
System.out.println(y); // 5
Я первые полгода путался с этим постоянно. Если не уверен — используй обычное x = x + 1, никто тебя не осудит. Кстати, интересный факт: в отличие от C++, в Java инкремент и декремент работают даже с float и double:
double price = 99.99;
price++;

System.out.println(price); // 100.99
Хотя для вещественных чисел это использовать не рекомендую — там свои приколы с точностью вычислений.

Побитовое дополнение

Оператор ~ переворачивает все биты числа. Все нули становятся единицами, все единицы — нулями. Выглядит как магия:
int a = 15;  // в двоичном виде: 00000000 00000000 00000000 00001111
int b = ~a;  // получаем:       11111111 11111111 11111111 11110000

System.out.println(b); // -16
Почему -16? Потому что Java хранит отрицательные числа в дополнительном коде. Но это уже другая история, и если ты на четвёртом уровне JavaRush — не парься пока об этом. Пригодится позже, когда будешь работать с низкоуровневыми операциями.

Арифметические операции — математика из школы

Тут всё знакомо: +, -, *, /. Работают как калькулятор, только с одним важным нюансом:
int x = 7;
int result = x / 4;

System.out.println(result); // 1, а не 1.75!
При делении целых чисел дробная часть просто отбрасывается. Если нужна точность — хотя бы одно число должно быть double:
double result = 7.0 / 4;
System.out.println(result); // 1.75

Остаток от деления — недооценённый герой

Оператор % возвращает остаток от деления. Кажется бесполезным? А вот и нет:
int number = 17;
boolean isEven = (number % 2 == 0);

System.out.println(isEven); // false — число нечётное
Проверка чётности — классика. А ещё с помощью остатка можно делать циклические переходы (например, в календарях или при работе с массивами).
// Остаток может быть отрицательным, если делимое отрицательное
int result1 = 7 % 4;   // 3
int result2 = -7 % 4;  // -3

System.out.println(result1);
System.out.println(result2);
И да, в Java оператор % работает даже с float и double, хотя я за десять лет ни разу не видел, чтобы кто-то использовал это в продакшене.

Побитовые операции — для продвинутых

Честно? На старте карьеры это использовать не будешь. Но знать надо, потому что на собеседованиях любят спрашивать.

Побитовое И, ИЛИ, исключающее ИЛИ

Побитовое И (&) — устанавливает бит в 1, только если оба бита равны 1:
int x = 12;  // 00001100
int y = 10;  // 00001010
int result = x & y; // 00001000

System.out.println(result); // 8
Побитовое ИЛИ (|) — устанавливает бит в 1, если хотя бы один бит равен 1:
int x = 12;  // 00001100
int y = 10;  // 00001010
int result = x | y; // 00001110

System.out.println(result); // 14
Исключающее ИЛИ (^) — устанавливает бит в 1, только если биты разные:
int x = 12;  // 00001100
int y = 10;  // 00001010
int result = x ^ y; // 00000110

System.out.println(result); // 6
Где это применяется? Например, в криптографии, при работе с флагами, в оптимизации алгоритмов. Но повторюсь — на первых порах это экзотика.

Битовые сдвиги

Сдвиг влево (<<) — умножает число на 2 в степени:
int x = 5;      // 00000101
int result = x << 2; // 00010100

System.out.println(result); // 20 (5 * 2^2)
Сдвиг вправо со знаком (>)) — делит число на 2 в степени, сохраняя знак:
int x = -20;    // 11111111 11111111 11111111 11101100
int result = x >> 2; // 11111111 11111111 11111111 11111011

System.out.println(result); // -5
Сдвиг вправо без знака (>>>) — заполняет старшие биты нулями:
int x = -20;
int result = x >>> 2;

System.out.println(result); // 1073741819 (огромное положительное число)
Последний оператор — это вообще экзотика редкая. Я его в реальном коде видел, наверное, два раза.

Составные операции присваивания — пиши короче

Вместо x = x + 5 можно писать x += 5. Короче и удобнее:
int score = 100;
score += 50;  // score = score + 50
score -= 20;  // score = score - 20
score *= 2;   // score = score * 2
score /= 3;   // score = score / 3

System.out.println(score); // 86
Работает со всеми арифметическими и побитовыми операциями: +=, -=, *=, /=, %=, &=, |=, ^=, <<=, >>=, >>>=. Интересная особенность — составные операции автоматически приводят типы:
byte b = 10;
b += 20; // компилируется!
// b = b + 20; — не компилируется, нужен каст

System.out.println(b); // 30
Это потому что при b = b + 20 результат сложения становится int, а запихнуть его обратно в byte без явного приведения нельзя. А составная операция делает приведение неявно.

Операции сравнения — основа любой логики

Всё просто: == (равно), != (не равно), >, >=, <, <=. Возвращают boolean:
int age = 25;

boolean isAdult = age >= 18;
boolean isTeen = age >= 13 && age <= 19;
boolean exactlyTwenty = age == 20;

System.out.println(isAdult);       // true
System.out.println(isTeen);        // false
System.out.println(exactlyTwenty); // false
Частая ошибка новичков — использовать один знак равенства вместо двух:
int x = 5;
if (x = 3) { // ОШИБКА! Компилятор ругается
    // ...
}
Компилятор Java умный — он не даст тебе запутаться. В отличие от C++, где такой код скомпилируется и будет работать неправильно.

Булевские операции — для работы с логикой

Логическое отрицание

Оператор ! переворачивает true в false и наоборот:
boolean isRaining = false;
boolean isSunny = !isRaining;

System.out.println(isSunny); // true

Логическое И и ИЛИ

Есть две версии этих операций, и вот тут начинается интересное. Обычные версии (& и |) — проверяют оба условия всегда:
boolean result = (5 > 3) & (10 / 0 > 1); // Бабах! ArithmeticException
Ленивые версии (&& и ||) — останавливаются, когда результат ясен:
boolean result = (5 < 3) && (10 / 0 > 1); // false, деление не выполнится!

System.out.println(result); // false
В реальной жизни почти всегда используют && и ||. Например, в проверках:
String name = null;

// Безопасно — сначала проверяем на null
if (name != null && name.length() > 0) {
    System.out.println("Имя задано");
}

// Опасно — вылетит с NullPointerException
// if (name.length() > 0 && name != null) { ... }

Исключающее ИЛИ

Оператор ^ возвращает true, только если операнды разные:
boolean hasTicket = true;
boolean hasInvitation = false;

boolean canEnter = hasTicket ^ hasInvitation; // true — есть что-то одно

System.out.println(canEnter);
Используется редко, но знать полезно.

Тернарный оператор — элегантный if

Синтаксис: условие ? значение_если_true : значение_если_false
int age = 20;
String status = (age >= 18) ? "Взрослый" : "Ребёнок";

System.out.println(status); // Взрослый
Компактно, но не увлекайся! Вложенные тернарные операторы — это путь к хаосу:
// Не делай так!
String result = (x > 0) ? (x > 10 ? "Много" : "Мало") : (x < -10 ? "Очень мало" : "Отрицательное");
Коллеги не скажут тебе спасибо за такой код.

Приоритет операций — кто главнее

Операции над примитивными типами в Java - 2Как в математике: сначала умножение и деление, потом сложение и вычитание. В Java похоже, только операторов больше:
int result = 2 + 3 * 4; // 14, а не 20

System.out.println(result);
Полный список приоритетов длинный и скучный. Мой совет — если не уверен, просто используй скобки:
int result = (2 + 3) * 4; // 20 — так понятнее

System.out.println(result);
Код читают люди, а не компиляторы. Лучше одна лишняя скобка, чем час на поиск ошибки.

Явное приведение типов — когда Java не догадывается

Иногда нужно "впихнуть" большой тип в маленький:
int bigNumber = 1000;
byte smallNumber = (byte) bigNumber; // явное приведение

System.out.println(smallNumber); // -24 — произошло переполнение!
Что случилось? byte может хранить только от -128 до 127. При переполнении Java берёт остаток от деления на 256. Это как счётчик на одометре — он же не может показать больше 999999, поэтому обнуляется и начинает заново. Будь осторожен с приведением типов! Это частая причина багов:
double price = 19.99;
int roundedPrice = (int) price; // отбрасывается дробная часть

System.out.println(roundedPrice); // 19, а не 20!
Если нужно округление — используй Math.round():
double price = 19.99;
int roundedPrice = (int) Math.round(price);

System.out.println(roundedPrice); // 20

Итоги

Операторы в Java — это как базовая грамматика в языке. Сначала кажется, что слишком много всего, но потом понимаешь: каждый день используешь всего 20% из них. Остальное — для особых случаев. Что реально важно знать: — Арифметические операции и составные присваивания — Операции сравнения — Логические &&, ||, ! — Инкремент и декремент (хотя бы отличать префикс от постфикса) — Тернарный оператор (но без фанатизма) Побитовые операции и битовые сдвиги? Ну... пригодятся, когда будешь готовиться к собеседованиям в Google или писать драйверы устройств. До этого можешь про них забыть.

Что ещё почитать

Примитивные типы Java