Цикл for
В цикле while из прошлого урока номер круга жил в трёх разных местах: переменную объявляли до цикла, проверяли в условии и меняли в конце тела. Стоит ошибиться в одном из трёх мест — и цикл не начнётся или не закончится.
У бегуна те же три дела. Перед стартом он один раз выставляет на табло 1. Перед каждым кругом смотрит на табло. После каждого круга прибавляет к номеру единицу.
Цикл for собирает все три дела в одну строку. Вот программа, которая складывает числа от 1 до 100:
public class Main {
public static void main(String[] args) {
int sum = 0;
for (int i = 1; i <= 100; i++) {
sum += i;
}
System.out.println(sum); // 5050
}
}Давайте разберём её по строкам:
int sum = 0;заводит сумму.for (int i = 1; i <= 100; i++)повторяет тело дляiот1до100.sum += i;прибавляет к сумме очередноеi. Дляintэта запись делает то же, чтоsum = sum + i, только короче.System.out.println(sum)выполняется после цикла и печатает5050.
Три части заголовка
Строку for (int i = 1; i <= 100; i++) называют заголовком цикла. В круглых скобках три части, разделённые точкой с запятой:
int i = 1— инициализация: выполняется один раз, до первой итерации. Бегун выставляет на табло1.i <= 100— условие: проверяется перед каждой итерацией, как вwhile. Бегун смотрит на табло.i++— шаг: выполняется после тела, перед следующей проверкой. Бегун прибавляет к номеру единицу.
Заголовок читается слева направо, но выполняется в другом порядке:
- Инициализация — один раз.
- Условие. Если оно ложно, цикл заканчивается.
- Тело.
- Шаг, и снова пункт 2.
Шаг записан в заголовке перед телом, а выполняется после него. Про этот порядок любят спрашивать на собеседованиях. В виджете тот же цикл, только до 3: нажимайте «Следующий шаг» и следите, какая часть заголовка выполняется сейчас.
1public class Main {2 public static void main(String[] args) {3 int sum = 0;4 for (int i = 1; i <= 3; i++) {5 sum += i;6 }7 System.out.println(sum);8 }9}
int sum = 0 заводит сумму.
Когда виджет дошёл до println, переменной i уже нет. Её объявили прямо в заголовке, и живёт она только внутри цикла.
Здесь картинка со стадионом расходится с Java. Табло на стадионе остаётся и после забега, а переменной из заголовка for после цикла не существует.
Другие формы заголовка
Шаг не обязан прибавлять единицу. -- вычитает единицу, а += прибавляет любое число:
for (int i = 0; i < 5; i++)— пять итераций,iот0до4;for (int i = 3; i >= 1; i--)— обратный отсчёт:3,2,1;for (int i = 0; i <= 10; i += 2)— чётные числа от0до10.
i++ и ++i
Оператор ++ прибавляет к переменной единицу. Его называют инкрементом, и у него две формы. Отдельной инструкцией, как в шаге цикла, они работают одинаково. Разница появляется, когда значение ++ идёт дальше: в печать, в присваивание, в другое выражение.
int n = 3;
System.out.println(n++); // 3
System.out.println(n); // 4
System.out.println(++n); // 5
System.out.println(n); // 5Постфиксная форма n++
++ стоит после имени. Выражение n++ даёт старое значение переменной, а единицу прибавляет уже потом. Поэтому первая строка печатает 3, хотя после неё n равна 4: это показывает вторая строка.
Префиксная форма ++n
++ стоит перед именем. Выражение ++n сначала прибавляет единицу, а потом даёт новое значение. Третья строка увеличивает n с 4 до 5 и печатает 5.
Запомнить помогает порядок записи: что стоит первым, то и происходит первым. В n++ первым стоит имя — сначала берётся значение. В ++n первым стоит ++ — сначала прибавляется единица. С -- всё так же: n-- даёт старое значение, --n — новое.
Эту разницу часто проверяют на собеседованиях: показывают короткую программу с i++ и ++i и спрашивают, что она напечатает. В своём коде, чтобы не путаться, пишите ++ отдельной инструкцией, а не внутри другого выражения.
Частая ошибка
Значение i понадобилось после цикла:
for (int i = 1; i <= 3; i++) {
System.out.print(i + " ");
}
System.out.println(i); // ✗error: cannot find symbolКомпилятор не знает имени i в последней строке: переменная из заголовка исчезла вместе с циклом. Сообщение то же, что для переменной, которую забыли объявить. Если значение нужно после цикла, храните его в переменной, объявленной до цикла, как sum в первом примере.
Главное
- Инициализация
forвыполняется один раз, условие — перед каждой итерацией, шаг — после тела. n++даёт старое значение и потом прибавляет единицу, а++nприбавляет единицу и даёт новое значение.- Отдельной инструкцией
i++и++iработают одинаково. - Переменная, объявленная в заголовке
for, существует только внутри цикла.