Menu

Цикл while в Java: синтаксис, do-while и частые ошибки

Цикл while в Java простыми словами: while, который проверяет условие сначала, do-while, выполняющийся хотя бы один раз, чтение ввода до сторожевого значения, break и continue и как избегать бесконечных циклов.

На этой странице есть исполняемые редакторы: меняйте, запускайте и сразу видите результат.

Когда у вас нет счётчика

Цикл for построен вокруг счётчика, который вы задаёте заранее. Но у многих циклов нет понятного счёта: читать строки, пока не закончится файл, запрашивать пароль, пока он не окажется верным, делить число пополам, пока оно не дойдёт до 1. Для таких случаев цикл while подходит естественно — он просто повторяется, пока условие остаётся истинным.

Цикл while проверяет условие перед каждым проходом, включая самый первый. Если условие ложно с самого начала, тело не выполняется вовсе.

Условие count > 0 проверяется первым; если оно истинно, выполняется тело; затем мы возвращаемся в начало и проверяем снова. Строка count-- — это то, что в итоге делает условие ложным; уберите её, и цикл будет выполняться вечно.

Анатомия цикла while

Сравните его с трёхчастным циклом for, который вы уже знаете. Цикл while разносит эти три задачи: инициализацию вы делаете до цикла, условие идёт в скобках, а обновление живёт внутри тела.

int i = 0;              // инициализация - до цикла
while (i < 5) {         // условие - проверяется на каждом проходе
    System.out.println(i);
    i++;                // обновление - о нём нужно помнить самому
}

Эта последняя часть и есть подвох. В цикле for обновление стоит прямо рядом с условием, поэтому его трудно забыть. В цикле while это просто ещё один оператор в теле — самая частая ошибка как раз в том, чтобы пропустить его и подвесить программу.

do-while: выполнить тело хотя бы один раз

Иногда нужно, чтобы тело выполнилось один раз прежде, чем вы вообще сможете решить, повторять ли. Цикл do-while проверяет условие в конце, поэтому тело всегда выполняется хотя бы один раз:

Нужно запросить и прочитать ввод хотя бы один раз, прежде чем вы сможете понять, корректен ли он, — именно это и даёт do-while. Обратите внимание на точку с запятой после while (...) — она обязательна, и её отсутствие — частая ошибка компиляции.

Отличие от обычного while ясно видно, когда условие изначально ложно:

Печатается только do-while body. Цикл while полностью пропускает своё тело, потому что x < 5 было ложным до первой проверки.

Цикл до сторожевого значения

Классическое применение while — читать до специального «стоп»-значения, сторожевого (sentinel). Здесь нет счётчика; вы просто продолжаете, пока данные не скажут вам остановиться:

Шаблон такой: прочитать один раз до цикла, затем читать снова в конце каждого прохода. Так условие всегда проверяет свежий ввод. Если вы забудете второе чтение внутри тела, value никогда не изменится — и вы получите бесконечный цикл.

break и continue в циклах while

break и continue работают здесь так же, как в цикле for. break немедленно покидает цикл; continue сразу переходит к проверке условия, пропуская остаток текущего прохода:

Это печатает 1 3 5 7 9. while (true) намеренно никогда не останавливается сам по себе — единственный выход — break. Будьте осторожны с continue в цикле while: поскольку обновление является частью тела, переход в начало через continue до того, как вы продвинули счётчик, — это тихий способ подвесить цикл. В примере выше n++ выполняется первым, поэтому всё безопасно.

Остерегайтесь бесконечных циклов

Условие должно в итоге стать ложным, и это целиком зависит от того, что что-то внутри тела меняется. Два обычных виновника — забыть про обновление и обновлять неправильно:

int i = 0;
while (i < 5) {
    System.out.println(i);   // i никогда не меняется -> выполняется вечно
}
int i = 0;
while (i != 10) {
    i += 3;   // 0, 3, 6, 9, 12... проскакивает мимо 10 -> выполняется вечно
}

Первый зависает, потому что i никогда не обновляется. Второй зависает, потому что счётчик перешагивает через точное значение, которое ищет условие; предпочитайте < или <= вместо !=, когда шаг может не попасть точно. while (true) допустим, если у него есть гарантированный break; случайный — это просто баг.

Далее: цикл for-each

Цикл while — правильный инструмент, когда вы повторяете до изменения условия и нет понятного счёта. Но когда вы просто хотите пройти по каждому элементу массива или списка — без индекса, без условия для управления — есть кое-что ещё чище: усовершенствованный цикл for-each. Это следующая страница.

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

В чём разница между while и do-while в Java?

Цикл while проверяет условие до первого прохода, поэтому тело может выполниться ноль раз. Цикл do-while сначала один раз выполняет тело, а затем проверяет условие в конце — поэтому он всегда выполняется хотя бы один раз. Используйте do-while, когда работу нужно сделать прежде, чем вы сможете решить, повторять ли её (например, запросить ввод, а затем проверить его).

Когда использовать цикл while вместо for в Java?

Используйте цикл while, когда у вас нет понятного счётчика и вы просто хотите повторять пока некое условие не изменится — читать ввод, пока пользователь не наберёт quit, опрашивать, пока значение не будет готово, или обрабатывать очередь, пока она не опустеет. Берите цикл for, когда знаете число итераций или у вас есть очевидный индекс для счёта.

Как остановить бесконечный цикл while в Java?

Убедитесь, что что-то внутри тела в итоге делает условие ложным (уменьшает счётчик, продвигает указатель, выставляет флаг). Для намеренного цикла while (true) поместите внутрь break, защищённый if. Если цикл зависает, обычная причина — забыли обновить переменную, от которой зависит условие.

Coddy programming languages illustration

Учитесь программировать с Coddy

НАЧАТЬ