Наверняка вы уже сталкивались с этими i++ и ++i в циклах. И если честно, первый раз видя это, многие думают примерно так: "Ну ладно, i++ понятно... а вот ++i это что вообще такое? И зачем?". Давайте разбираться. Тема на самом деле простая, но есть один нюанс, который часто ставит новичков в тупик.Что такое инкрементирование и декрементирование - 1

Что такое инкремент и декремент простыми словами

Начнём с базы. Инкремент — это когда ты увеличиваешь переменную на единицу. Пишется как два плюса: ++ Декремент — соответственно, уменьшаешь на единицу. Два минуса: -- Можно представить это так: вы охранник на входе в клуб и считаете гостей. Зашёл один человек — щёлк на счётчике, плюс один. Это инкремент. Вышел кто-то — минус один, декремент. Всё просто, правда? Вот как это выглядит в коде:
int visitors = 10;
visitors++;  // теперь visitors = 11
visitors--;  // снова visitors = 10

System.out.println(visitors);  // выведет: 10
Да, можно было бы написать visitors = visitors + 1. Но согласитесь, visitors++ выглядит куда лаконичнее. Зачем усложнять жизнь?

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

А теперь держитесь! У инкремента и декремента есть две формы записи, и именно здесь обычно начинаются вопросы. Префиксная форма (prefix) — когда оператор стоит перед переменной: ++x или --x Постфиксная форма (postfix) — когда оператор идёт после: x++ или x-- Смотрите. Если вы просто увеличиваете переменную, без всяких вычислений — то абсолютно без разницы, какую форму использовать:
int x = 10;
int y = 10;

x++;   // x теперь 11
++y;   // y тоже 11

System.out.println("x: " + x + ", y: " + y);  // выведет: x: 11, y: 11
Результат один и тот же. Но! Когда вы начинаете использовать инкремент прямо внутри какого-то выражения — вот тут начинается интересное.

Постфиксная форма: используй сейчас, увеличь потом

Постфиксная форма работает по принципу "сначала отдай то что есть, потом измени". Помните нашего охранника с табличкой? Представьте: заходит посетитель, второй охранник спрашивает "сколько народу?". Вы показываете табличку с текущей цифрой (допустим, 10), он записывает это число. И только после этого вы меняете цифру на табличке на 11.
int visitors = 10;
int reportedNumber = visitors++;

System.out.println("Сообщили: " + reportedNumber);  // выведет: 10
System.out.println("Реально в зале: " + visitors);  // выведет: 11
Видите? Сначала значение visitors (которое было 10) ушло в reportedNumber. И только потом visitors увеличился до 11.

Префиксная форма: измени сразу, потом используй

С префиксом всё наоборот. Тут правило "сначала измени, а потом работай с новым значением". Та же ситуация с охранником, но теперь вы сначала меняете цифру на табличке (10 становится 11), а уже потом показываете её коллеге. Он и записывает 11.
int visitors = 10;
int reportedNumber = ++visitors;

System.out.println("Сообщили: " + reportedNumber);  // выведет: 11
System.out.println("Реально в зале: " + visitors);  // выведет: 11

Разбираем на живых примерах

Ладно, теория — это хорошо. Но давайте посмотрим, как это реально работает в коде с вычислениями:
int x = 10;
int c = 10;

int y = 13 - x++;  // постфиксная форма
int z = 13 - ++c;  // префиксная форма

System.out.println("y: " + y + ", z: " + z);  // выведет: y: 3, z: 2
System.out.println("x: " + x + ", c: " + c);  // выведет: x: 11, c: 11
Стоп. И x, и c изначально равны 10. Выражения вроде одинаковые. Но результаты разные — y = 3, а z = 2! Как так? Давайте по шагам разберём каждый случай. Постфиксная форма (x++):
// x = 10
// Шаг 1: берём текущее значение x (оно пока 10) и используем в вычислении
y = 13 - 10;  // получается y = 3
// Шаг 2: и только сейчас x увеличивается
x = 11;
Префиксная форма (++c):
// c = 10
// Шаг 1: сразу увеличиваем c
c = 11;
// Шаг 2: теперь используем уже новое значение (11) в вычислении
z = 13 - 11;  // получается z = 2
Вот и вся разница! В первом случае мы взяли старое значение для расчёта, во втором — сначала изменили, потом посчитали.

Типичные ошибки (и как не наступать на эти грабли)

Ошибка 1: "Почему i++ не возвращает увеличенное значение?"

Классика! Многие ожидают, что i++ сразу вернёт новое значение. Но нет:
int i = 5;
System.out.println(i++);  // выведет 5, а не 6!
System.out.println(i);    // а вот теперь будет 6
Если нужно именно увеличенное значение сразу — используйте префикс:
int i = 5;
System.out.println(++i);  // выведет 6

Ошибка 2: Сложные выражения с кучей инкрементов

Вот это вообще не делайте, пожалуйста:
int x = 5;
int result = x++ + ++x + x++;  // кто вообще это придумал?!
Серьёзно, даже опытные разработчики будут минут 10 разбираться, что тут происходит. А ещё легко ошибиться. Лучше так:
int x = 5;
x++;
int result = x;
x++;
result += x;
x++;
result += x;
Да, получилось длиннее. Зато через месяц, когда вы вернётесь к этому коду, сразу поймёте что к чему.

Ошибка 3: Инкремент в индексах массивов

Ещё одна засада — когда инкремент используется прямо в индексе массива:
int[] numbers = {10, 20, 30};
int i = 0;

// Что тут вообще произойдёт?
numbers[i] = numbers[i++];
Тут можно такого наворотить... Лучше не рисковать и писать явно:
numbers[i] = numbers[i];
i++;
Скучно? Может быть. Зато работает предсказуемо.

А где это вообще применяется?

Нормальные варианты использования: 1. В циклах for — тут это классика жанра:
for (int i = 0; i < 10; i++) {
    System.out.println(i);
}
2. Счётчики:
int errorCount = 0;
if (hasError) {
    errorCount++;
}
3. Перебор элементов в цикле:
int index = 0;
while (index < array.length) {
    process(array[index++]);
}
Когда лучше НЕ использовать: - Если выражение получается сложным и непонятным — лучше разбить на несколько строк - Иногда просто += 1 будет читаться понятнее - В современном Java вообще часто можно обойтись forEach или Stream API вместо циклов со счётчиками

Коротко о главном

Давайте ещё раз пробежимся по основным моментам: • ++ увеличивает на единицу, -- уменьшает • x++ (постфикс) — используем старое значение, потом меняем переменную • ++x (префикс) — сначала меняем переменную, потом используем новое значение • Если инкремент стоит отдельной строкой — без разницы какую форму использовать • Не пишите сложные выражения с кучей инкрементов. Просто не надо. • Золотое правило: если сами не уверены, что код делает — упростите его Знаете, инкремент и декремент — штуки простые, но поначалу могут здорово запутать. Особенно эта разница между префиксом и постфиксом. Не переживайте, если с первого раза не всё понятно — это нормально! Лучший способ разобраться — просто больше практиковаться. Попробуйте написать несколько примеров самостоятельно, поэкспериментируйте с разными вариантами. Запустите код, посмотрите что выводится. Очень скоро вы будете использовать эти операторы автоматически, даже не задумываясь. Удачи в изучении Java!