Наверняка вы уже сталкивались с этими 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 вместо циклов со счётчиками
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ