Оператор
Сегодня мы рассмотрим такую возможность языка программирования Java, как оператор перехода break. Это первая статья на тему операторов перехода, так что если вам понравится, буду рад написать еще. Сразу хочу заметить, что эта статья рассчитана в первую очередь на начинающих разработчиков, и более продвинутые ученики могут не найти здесь чего-то нового для себя. Итак, поехали.
В Java существует 2 способа изменить порядок выполнения инструкций программы: операторы перехода и механизм обработки исключений. К операторам перехода в java относят три оператора: break, continue и return. Сегодня же я предлагаю Вам рассмотреть подробнее оператор
break в Java прерывает выполнение и передает управление за пределы конструкции, в которой он стоит. Применяют его тремя способами: досрочный выход из цикла, завершение ветки switch и выход из помеченного блока кода (break метка;), который заменяет в Java отсутствующий goto (JLS, раздел 14.15). Без метки break действует только на ближайший окружающий цикл или switch. Ниже все три способа с примерами и выводом программ.Кратко
- В цикле
breakзавершает его досрочно, и выполнение продолжается со строки после цикла. - Из вложенных циклов обычный
breakвыходит только во внешний, то есть прерывает лишь самый внутренний цикл. - В
switchбезbreakначинается провал: после подошедшей ветки выполняются и все следующие. Иногда это удобно, когда несколькоcaseподряд ведут к одному действию. break метка;выходит сразу из нескольких вложенных блоков или циклов; прыгнуть можно только наружу из блока, который содержит этотbreak, иначе код не скомпилируется.- Злоупотреблять
breakне стоит: чем длиннее и глубже цикл, тем сильнее лишние выходы мешают читать код. - В
switchсо стрелкой (Java 14 и новее)breakмежду ветками не нужен вообще: провала там нет.

break. Механизм обработки исключений является столь обширной темой, что выходит за рамки данной статьи.
Есть три способа применения оператора break в java.Способ 1: досрочный выход из цикла
Первый и самый популярный способ это использованиеbreak для досрочного выхода из цикла, например:
public class SimpleExample {
public static void main(String[] args) {
findNumberInLoop(3);
}
public static void findNumberInLoop(int number){
for (int i = 0; i < 10; i++) {
if (i == number) {
break;
}
System.out.println(i);
}
System.out.println("cycle was finished");
}
}
Этот пример выведет на экран:
0
1
2
cycle was finished
Это означает, что когда счетчик цикла i становится равным переданному параметру number, то есть числу 3, выполнение цикла прерывается досрочно.
Если в программе есть несколько вложенных друг в друга циклов, то break выводит только из самого внутреннего цикла, например:
public class SimpleExample {
public static void main(String[] args) {
findNumberInLoop(3);
}
public static void findNumberInLoop(int number){
for(int i = 0; i < 5; i++) {
for (int j =0; j < 10; j++) {
if(j == number) {
break;
}
System.out.print(j);
}
System.out.println();
}
System.out.println("cycles was finished");
}
}
Этот пример дает вывод:
012
012
012
012
012
cycles was finished
Как видно из примера, внутренний цикл каждый раз прерывается на числе 3 (параметр number), а внешний цикл выполняется 5 раз, как было и задумано. В java можно использовать более одного оператора break внутри цикла, но этого делать не рекомендуется, так как очень сильно ухудшается читабельность и структура кода.
Способ 2: break в ветвях switch
Второй способ примененияbreak заключается в использовании его для прерывания выполнения операторов в ветвях switch, например:
public class SimpleExample {
public static void main(String[] args) {
square(2);
}
public static void square(int number){
switch (number){
case 1:
System.out.println(number*number);
break;
case 2:
System.out.println(number*number);
break;
case 3:
System.out.println(number*number);
break;
}
System.out.println("after switch");
}
}
Запуск этого примера даст вывод:
4
after switch
Оператор break передал управление коду следующему за всем блоком switch. Если же не указать break в switch в данном примере:
public class SimpleExample {
public static void main(String[] args) {
square(2);
}
public static void square(int number){
switch (number){
case 1:
System.out.println(number*number);
case 2:
System.out.println(number*number);
case 3:
System.out.println(number*number);
}
System.out.println("after switch");
}
}
Вывод будет не таким как ожидалось:
4
4
after switch
Это произошло потому, что после выполнения блока case 2 программа продолжила выполнять все следующие за ним блоки case, что и дало нам соответствующий вывод.
Такое поведение (его называют провалом, fall-through) осталось только у классического switch с двоеточиями. С Java 14 есть форма со стрелкой (JEP 361): в ней выполняется ровно одна ветка, поэтому break писать не нужно, а перечислить несколько значений можно через запятую, case 0, 1, 2, 3, 4, 5 -> .... Подробнее про обе формы в статье про оператор switch.
Иногда такая особенность оператора switch может быть нам выгодна, например:
public class SimpleExample {
public static void main(String[] args) {
compare(2);
compare(7);
compare(12);
}
public static void compare(int number){
switch (number){
case 0:
case 1:
case 2:
case 3:
case 4:
case 5:
System.out.println("number is less than 5 or equal 5");
break;
case 6:
case 7:
case 8:
case 9:
System.out.println("number is greater than 5");
break;
default:
System.out.println("number is less than 0 or greater than 9");
}
System.out.println("after switch");
}
}
Данная программа реализует сравнение заданного числа с числом 5 и дает следующий вывод:
number is less than 5 or equal 5
after switch
number is greater than 5
after switch
number is less than 0 or greater than 9
after switch
При первом вызове метода, оператор switch передает управление оператору case 2 и далее до оператора break в case 5. Второй вызов происходит по аналогии с первым, но начинается с case 7. Третий вызов не находит подходящего значения среди всех case’ов, поэтому выполняется оператор default.
Способ 3: break с меткой вместо goto
Третий способ заключается в использовании оператораbreak вместо оператора goto из языка C. Для этого мы будем использовать особую форму оператора break, называемую break с меткой. Эта форма выглядит как break метка; Метка это, как правило, любое подходящее имя из пространства имен java, предваряющее блок кода. Применение в этом блоке кода break с меткой приведет к тому, что код продолжит выполняться с места после блока с соответствующей меткой, например:
public class SimpleExample {
public static void main(String[] args) {
howWeUseLabels(true);
System.out.println();
howWeUseLabels(false);
}
public static void howWeUseLabels(boolean bool) {
firstBlock:{
secondBlock:{
thirdBlock:{
System.out.println("We will see it always");
if(bool) {
break secondBlock;
}
System.out.println("We won't see it if bool == true");
}
System.out.println("We won't see it if bool == true");
}
System.out.println("We will see it always");
}
}
}
Этот пример даст следующий вывод:
We will see it always
We will see it always
We will see it always
We won't see it if bool == true
We won't see it if bool == true
We will see it always
После первого вызова метода, оператор break осуществляет передачу управления в конец блока secondBlock, выходя из secondBlock и thirdBlock, при этом выполняя еще один оператор println(), в конце firstBlock. После второго вызова на экран выводится все строки.
Метки можно использовать также для обозначения циклов. Именно так чаще всего и поступают на практике: обычный break выходит только из внутреннего цикла, а break с меткой прерывает сразу оба, например поиск числа в матрице:
public class SimpleExample {
public static void main(String[] args) {
int[][] matrix = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}};
int number = 5;
search:
for (int i = 0; i < matrix.length; i++) {
for (int j = 0; j < matrix[i].length; j++) {
System.out.println("Проверяем matrix[" + i + "][" + j + "] = " + matrix[i][j]);
if (matrix[i][j] == number) {
System.out.println("Число " + number + " найдено в строке " + i + ", столбце " + j);
break search;
}
}
}
System.out.println("Поиск завершен");
}
}
Вывод этого примера:
Проверяем matrix[0][0] = 1
Проверяем matrix[0][1] = 2
Проверяем matrix[0][2] = 3
Проверяем matrix[1][0] = 4
Проверяем matrix[1][1] = 5
Число 5 найдено в строке 1, столбце 1
Поиск завершен
Без метки внешний цикл продолжил бы работу и прошел бы оставшиеся строки матрицы.
При этом следует помнить, что переходить к метке можно только изнутри блока кода, обозначенного меткой, например такой код не скомпилируется:
public class SimpleExample {
public static void main(String[] args) {
label:{
System.out.println("inside label");
}
if(true) {
break label;
}
System.out.println("This is error");
}
}
Компилятор остановится на строке break label; с ошибкой undefined label: label: блок с меткой label к этому моменту уже закончился, а значит не содержит данный break.Чистота кода и оператор break
Существует общепризнанный совет использовать операторbreak очень осторожно, так как применение break усложняет понимание цикла и заставляет программиста заглянуть внутрь цикла, чтобы разобраться в нюансах его работы. Есть эвристическое правило, что использовать break можно увереннее в более коротких циклах и с большей осторожностью в длинных и имеющих глубокую вложенность, так как это увеличивает вероятность ошибки и усложняет чтение и понимание вашего кода другими программистами. Как я уже писал выше, использование большого количества break, разбросанных по всему коду, говорит о том, что программист не до конца понимает, почему он написал свой код именно так. Возможно, стоит рассмотреть рефакторинг такого цикла, путем разбиения на несколько более маленьких циклов. Старайтесь с осторожностью использовать break с меткой в качестве замены goto, так как это усложняет структуру кода.
Вот и все, что я хотел сегодня рассказать об операторе break в java. Буду рад конструктивной критике, а также готов написать продолжение про операторы continue и return, если Вам это интересно. Пока же о них можно почитать в статье про break, continue и return.
Вопросы и ответы
Что делает оператор break в Java?
Прерывает выполнение ближайшего окружающего цикла (for, while, do-while) или switch и передает управление на строку сразу после него. Форма с меткой, break метка;, выходит из помеченного блока, даже если это несколько вложенных циклов. Прервать метод break не может: для этого есть return.
Как выйти из двух вложенных циклов сразу?
Обычныйbreak прерывает только внутренний цикл, поэтому внешнему нужна метка: outer: for (...) { for (...) { if (условие) break outer; } }. Альтернативы: вынести циклы в отдельный метод и завершить его через return или завести булев флаг и проверять его в условии внешнего цикла.
Что будет, если забыть break в switch?
Начнется провал (fall-through): после сработавшей ветки выполнятся и все следующие, до ближайшегоbreak или до конца switch. Например, при number = 2 и ветках без break выполнятся и case 2, и case 3. Иногда провал используют намеренно: несколько case подряд без тела ведут к одному общему действию.
Чем break отличается от continue и return?
break завершает весь цикл, continue только текущую итерацию: он пропускает остаток тела и переходит к следующему шагу цикла. return завершает метод целиком и возвращает управление вызывающему коду, поэтому выходит и из всех циклов сразу. Разбор всех трех есть в соседней статье про операторы break, continue и return.
Что такое break с меткой и заменяет ли он goto?
Метка это идентификатор с двоеточием перед блоком или циклом:firstBlock: { ... }. Команда break firstBlock; продолжает выполнение сразу после этого блока. Оператора goto в Java нет, и метка не полноценная его замена: перейти можно только наружу из блока, внутри которого стоит сам break. Попытка прыгнуть в чужой блок это ошибка компиляции (JLS, раздел 14.15).
Нужен ли break в switch со стрелкой?
Нет. В формеcase 2 -> System.out.println(4);, появившейся в Java 14, выполняется ровно одна ветка, провала нет, и break не нужен. Более того, в switch-выражении break со значением не используется: чтобы вернуть результат из блока в фигурных скобках, пишут yield. Классический switch с двоеточиями продолжает работать по-старому, там break обязателен.
Читайте также:
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ