Вступление
Условные операторы и циклы - очень важный инструмент в программировании. Есть немного вещей, которые мы могли бы сделать с кодом, который может выполняться только построчно.
Вот что означает «управление потоком» - руководство выполнением нашей
программы вместо того, чтобы позволить ей выполняться построчно,
независимо от каких-либо внутренних или внешних факторов. Каждый язык
программирования поддерживает некоторую форму управления потоком, если
не явно через if
s и for
s или аналогичные операторы - тогда он
неявно дает нам инструменты для создания таких конструкций, то есть
языки программирования низкого уровня обычно достигают этого эффекта с
большим go-to
командам.
Циклы были концепцией, которая использовалась задолго до того, как компьютерное программирование стало вообще чем-то, но первой, кто использовал программный цикл, была Ада Лавлейс, широко известная под своей девичьей фамилией - Байрон, при вычислении чисел Бернулли еще в 19 веке.
В Java есть несколько способов управления потоком кода:
- операторы if и if-else
- операторы переключения
- утверждения
while
иdo-while
for
иenhanced for
операторов- операторы
break
иcontinue
перерыв
Оператор break
является одним из «операторов перехода» Java, поскольку
он передает выполнение кода другой части кода. Мы уже видели ключевое
слово break
используемое в операторе
switch . Мы вернемся к этому
здесь вместе с другими вариантами использования:
- Его можно использовать, чтобы остановить выполнение
switch
, вместо того, чтобы позволить ему продолжить выполнение кода для следующих случаев. - Его можно использовать для выхода из цикла до того, как он завершит все его итерации, или как форму выхода из специально созданных бесконечных циклов.
- Его можно использовать в качестве приемлемой формы оператора перехода, когда у нас есть несколько вложенных циклов.
Первые два относительно похожи, поскольку оба используются для преждевременного завершения выполнения одного или нескольких блоков кода:
// Finding at which index element a is in an array
int[] arr = {1,2,3,4,5,6};
int foundAt = -1;
int a = 4;
for (int i = 0; i < arr.length; i++) {
System.out.println(arr[i]);
if (arr[i] == a) {
foundAt = i;
break;
}
}
if (foundAt != -1)
System.out.println(a + " was found at index " + foundAt);
else System.out.println(a + " wasn't found in the array");
Выход:
1
2
3
4
4 was found at index 3
Как мы видим, for
выполнялся как обычно, пока не встретился с break
, после чего Java прекратила выполнение цикла и продолжила выполнение с
первой строки после цикла for
.
Вот еще один пример:
Scanner s = new Scanner(System.in);
while (true) {
System.out.println("Do you wish to exit the infinite loop? Y/N");
if (s.hasNext()) {
String answer = s.next();
if (answer.equals("Y") || answer.equals("y"))
break;
}
}
Этот цикл будет продолжать спрашивать пользователя, хочет ли он выйти из
цикла, пока он не ответит соответствующими символами, где мы выйдем из
цикла с помощью break
, или завершим программу с помощью Ctrl + C
По умолчанию break
завершает только самый внутренний цикл, в котором
он находится.
Если мы хотим , чтобы найти первую позицию , в которой определенный
элемент можно найти в матрице, и мы хотели break
из петли , как только
мы его (аналогично примеру с массивом выше) обнаружили, написав
следующее Wouldn не работает:
int[][] matrix = {{1,2,3},{4,5,6},{7,8,9}};
int foundAtI = -1;
int foundAtJ = -1;
int a = 4;
for (int i = 0; i < matrix.length; i++) {
for (int j = 0; j < matrix[i].length; j++) {
System.out.print(matrix[i][j] + " ");
if (matrix[i][j] == a) {
foundAtI = i;
foundAtJ = j;
break;
}
}
System.out.println();
}
System.out.println();
if (foundAtI != -1)
System.out.println(a + " was found at indices [" + foundAtI + "," + foundAtJ + "]");
else System.out.println(a + " wasn't found in the matrix");
Выход:
1 2 3
4
7 8 9
4 was found at indices [1,0]
Мы видим, что цикл продолжал выполняться даже после нахождения 4 в
матрице, после заикания в строке, в которой находилось 4. Это связано с
тем, что break
завершил только самый внутренний цикл, то есть
прекратил итерацию по текущей строке и перешел к следующей. Кроме того,
наша задача состояла в том, чтобы найти первое вхождение 4 в матрицу, и
таким образом мы вернем последнее вхождение 4 в нашу матрицу.
Здесь в игру вступают помеченные утверждения , которые мы рассмотрим дальше.
Помеченные заявления
Отмеченные операторы могут использоваться вместе с break
или
continue
для имитации go-to
.
Метки могут быть применены к любому блоку кода между {}
, for
,
for-each
, while
, do-while
, if
и switch
, а также
выражениями, присваиваниями, операторами return
, блоками try
и
операторами throw
Затем мы используем их с операторами break
и
continue
Ярлыки работают путем применения идентификатора к конструкции:
Identifier : Construct
Такой как:
someLoop: for (int i = 0; i < 100; i++) {}
someLabel: {
int i = 10;
}
Затем мы можем вызвать эти помеченные операторы через break
или
continue
. Например, здесь мы обозначили наш внешний цикл просто
outer
. Чтобы выйти из двух или более вложенных циклов, мы break
внешний цикл, вызывая метку:
outer: for (int i = 0; i < matrix.length; i++) {
for (int j = 0; j < matrix[i].length; j++) {
System.out.print(matrix[i][j] + " ");
if (matrix[i][j] == a) {
foundAtI = i;
foundAtJ = j;
break outer;
}
}
System.out.println();
}
Использование этого помеченного цикла вместо цикла в приведенном выше примере дает правильный результат и поведение:
1 2 3
4
4 was found at indices [1,0]
Вы не можете использовать break label
если break
не находится в
блоке кода, обозначенном этой меткой, или это вызовет ошибку во время
компиляции.
Продолжать
Оператор continue
просто пропускает оставшуюся часть текущей
итерации и переходит к следующей. Это полезно, когда мы хотим пропустить
целые (или часть) итераций, которые соответствуют определенным условиям,
особенно если они требуют высокой производительности.
Для в while
цикла, «пропуск» остальные итерации средств , идущих прямо
назад проверить состояние до следующей итерации, а для for
цикла этого
средства будет «ступенчатой» часть for
цикла (ту часть , где мы обычно
увеличить / уменьшить управляющую переменную), а затем проверить условие
перед следующей итерацией.
continue
обычно используется с оператором if
-> мы continue
если
будет выполнено определенное условие. Мы используем это, if
выполняем
оставшуюся часть итерации, только если условие не выполняется, и
пропускаем использование continue
. Например
// We want to print every number from 1 to 20, except those divisible by 3
for (int i = 1; i <= 20; i++) {
if (i % 3 == 0)
continue;
System.out.println(i);
}
continue
в нашем примере можно было бы легко избежать, используя
слегка измененный if
, в основном печатая число, если i % 3 != 0
истинно, иначе ничего не делая.
Общий совет относительно как break
и (особенно) continue
- пытаться
использовать их в основном в начале итераций в качестве некоторой формы
предварительных условий, которые мы проверяем. Использование continue
где-нибудь в середине итерации - отличный способ вызвать ошибки, на
выяснение которых у вас уйдет время.
Конечно, вы также можете использовать continue
с помеченными
операторами:
start: for (int i = 0; i < 10; i++) {
System.out.println();
for (int j = 0; j < 10; j++) {
if (j >= i)
continue start;
}
System.out.println("Since j will always be equal to or more than i, the 'start' loop will continue running indefinitely, and this piece of code will never run.");
}
Заключение
Управление потоком в коде важно практически для каждого приложения. Заявления, которые изменяют поток кода, являются фундаментальными строительными блоками, и каждый начинающий разработчик должен полностью контролировать / осознавать, как они работают.
Используя break
и continue
, разработчики Java могут имитировать
go-to
и при необходимости выходить из определенных циклов.