What is the «continue» keyword and how does it work in Java?
continue is kind of like goto . Are you familiar with break ? It’s easier to think about them in contrast:
- break terminates the loop (jumps to the code below it).
- continue terminates the rest of the processing of the code within the loop for the current iteration, but continues the loop.
A continue statement without a label will re-execute from the condition the innermost while or do loop, and from the update expression of the innermost for loop. It is often used to early-terminate a loop’s processing and thereby avoid deeply-nested if statements. In the following example continue will get the next line, without processing the following statement in the loop.
With a label, continue will re-execute from the loop with the corresponding label, rather than the innermost loop. This can be used to escape deeply-nested loops, or simply for clarity.
Sometimes continue is also used as a placeholder in order to make an empty loop body more clear.
for (count = 0; foo.moreData(); count++) continue;
The same statement without a label also exists in C and C++. The equivalent in Perl is next .
This type of control flow is not recommended, but if you so choose you can also use continue to simulate a limited form of goto . In the following example the continue will re-execute the empty for (;;) loop.
I would add the caveat that if you have to use a continue keyword, then your loop is busted at a fundamental level and you will be using more memory than you need to and your loop logic is now busted.
This would get the sum of only odd numbers from 1 to 100.
If you think of the body of a loop as a subroutine, continue is sort of like return . The same keyword exists in C, and serves the same purpose. Here’s a contrived example:
for(int i=0; i < 10; ++i) < if (i % 2 == 0) < continue; >System.out.println(i); >
This will print out only the odd numbers.
Generally, I see continue (and break ) as a warning that the code might use some refactoring, especially if the while or for loop declaration isn’t immediately in sight. The same is true for return in the middle of a method, but for a slightly different reason.
As others have already said, continue moves along to the next iteration of the loop, while break moves out of the enclosing loop.
These can be maintenance timebombs because there is no immediate link between the continue / break and the loop it is continuing/breaking other than context; add an inner loop or move the «guts» of the loop into a separate method and you have a hidden effect of the continue / break failing.
IMHO, it’s best to use them as a measure of last resort, and then to make sure their use is grouped together tightly at the start or end of the loop so that the next developer can see the «bounds» of the loop in one screen.
continue , break , and return (other than the One True Return at the end of your method) all fall into the general category of «hidden GOTOs». They place loop and function control in unexpected places, which then eventually causes bugs.
Операторы перехода break, continue, return
В Java есть три оператора перехода: break, continue, return. Операторы перехода передают управление другой части программы.
Оператор break
Оператор break завершает последовательность операторов в операторе switch, позволяет выйти из цикла и в качестве оператора безусловного перехода (goto).
Рассмотрим пример выхода из цикла. Используя оператор break, можно вызвать немедленное завершение цикла, пропуская условное выражение и другой код в теле цикла. Когда приложение встречает оператор break внутри цикла, оно прекращает выполнение цикла и передаёт управление оператору, следующему за циклом.
for(int i = 0; i < 100; i++) < if(i == 5) break; // выходим из цикла, если i равно 5 mInfoTextView.append("i: " + i + "\n"); >mInfoTextView.append("Цикл завершён");
Получим следующий результат:
i: 0 i: 1 i: 2 i: 3 i: 4 Цикл завершён
Вроде хотели, чтобы цикл for выполнялся от 0 до 100, а сами коварно вышли из него, когда значение переменной i стало равным 4.
Код можно переписать с использованием цикла while:
int i = 0; while(i < 100) < if(i == 5) break; // выходим из цикла, если i равно 5 mInfoTextView.append("i: " + i + "\n"); i++; >mInfoTextView.append("Цикл завершён");
При использовании вложенных циклов оператор break осуществляет выход только из самого внутреннего цикла, не оказывая влияния на внешний цикл. Создадим пример с использованием вложенных циклов:
for (int i = 1; i < 4; i++) < mInfoTextView.append("Проход " + i + ": "); for (int j = 0; j < 100; j++) < if (j == 5) break; // выходим из цикла, если j равно 5 mInfoTextView.append(j + " "); >mInfoTextView.append("\n"); > mInfoTextView.append("Циклы завершёны");
Получим следующий результат:
Проход 1: 0 1 2 3 4 Проход 2: 0 1 2 3 4 Проход 3: 0 1 2 3 4 Циклы завершёны
В примере оператор break прервал выполнение второго цикла, но первый цикл продолжал работать.
В цикле можно использовать несколько операторов break, но увлекаться не стоит. Лучше переделайте код.
break как замена goto
В Java нет оператора безусловного перехода goto. Если вы не знаете, что это такое, то можете смело пропустить данный абзац. У оператора break есть особая форма записи:
Обычно метка — это имя метки, идентифицирующей блок кода. Я ни разу не встречал в реальных примерах данный способ, поэтому не буду приводить пример использования, чтобы вас не запутать.
Оператор continue
Иногда требуется, чтобы повторение цикла начиналось с более раннего оператора его тела. В циклах while и do-while оператор continue вызывает передачу управления непосредственно управляющему условному выражению цикла. В цикле for управление передаётся вначале итерационной части цикла for, а потом условному выражению. При этом во всех циклах промежуточный код пропускается.
В следующем примере выводим два числа в каждой строке:
В этом коде оператор % служит для проверки чётности значения переменной i. Если значение чётное, выполнение цикла продолжится дальше, а если нечётное, то произойдёт переход на новую строку. В результате мы получим следующий текст:
Как и оператор break, оператор continue может содержать метку содержащего его цикла, который нужно продолжить. Создадим пример вывода треугольной таблицы умножения чисел от 0 до 9.
outer: for (int i = 0; i < 10; i++) < for (int j = 0; j < 10; j++) < if (j >i) < mInfoTextView.append("\n"); continue outer; >mInfoTextView.append(" " + (i * j)); > > mInfoTextView.append("\n");
В этом примере оператор continue прерывает цикл подсчёта значений переменной j и продолжает его со следующей итерации цикла подсчёта переменной i. На экране увидим текст в таком виде:
0 0 1 0 2 4 0 3 6 9 0 4 8 12 16 и т.д.
Данный оператор в практике встречается достаточно редко. Но на всякий случай помните о нём. Иногда он может пригодиться.
Оператор return
Оператор return используют для выполнения явного выхода из метода. Оператор можно использовать в любом месте метода для возврата управления тому объекту, который вызвал данный метод. Таким образом, return прекращает выполнение метода, в котором он находится.
Branching Statements
The break statement has two forms: labeled and unlabeled. You saw the unlabeled form in the previous discussion of the switch statement. You can also use an unlabeled break to terminate a for , while , or do-while loop, as shown in the following BreakDemo program:
class BreakDemo < public static void main(String[] args) < int[] arrayOfInts = < 32, 87, 3, 589, 12, 1076, 2000, 8, 622, 127 >; int searchfor = 12; int i; boolean foundIt = false; for (i = 0; i < arrayOfInts.length; i++) < if (arrayOfInts[i] == searchfor) < foundIt = true; break; > > if (foundIt) < System.out.println("Found " + searchfor + " at index " + i); >else < System.out.println(searchfor + " not in the array"); >> >
This program searches for the number 12 in an array. The break statement, shown in boldface, terminates the for loop when that value is found. Control flow then transfers to the statement after the for loop. This program’s output is:
An unlabeled break statement terminates the innermost switch , for , while , or do-while statement, but a labeled break terminates an outer statement. The following program, BreakWithLabelDemo , is similar to the previous program, but uses nested for loops to search for a value in a two-dimensional array. When the value is found, a labeled break terminates the outer for loop (labeled «search»):
class BreakWithLabelDemo < public static void main(String[] args) < int[][] arrayOfInts = < < 32, 87, 3, 589 >, < 12, 1076, 2000, 8 >, < 622, 127, 77, 955 >>; int searchfor = 12; int i; int j = 0; boolean foundIt = false; search: for (i = 0; i < arrayOfInts.length; i++) < for (j = 0; j < arrayOfInts[i].length; j++) < if (arrayOfInts[i][j] == searchfor) < foundIt = true; break search; >> > if (foundIt) < System.out.println("Found " + searchfor + " at " + i + ", " + j); >else < System.out.println(searchfor + " not in the array"); >> >
This is the output of the program.
The break statement terminates the labeled statement; it does not transfer the flow of control to the label. Control flow is transferred to the statement immediately following the labeled (terminated) statement.
The continue Statement
The continue statement skips the current iteration of a for , while , or do-while loop. The unlabeled form skips to the end of the innermost loop’s body and evaluates the boolean expression that controls the loop. The following program, ContinueDemo , steps through a String , counting the occurrences of the letter «p». If the current character is not a p, the continue statement skips the rest of the loop and proceeds to the next character. If it is a «p», the program increments the letter count.
class ContinueDemo < public static void main(String[] args) < String searchMe = "peter piper picked a " + "peck of pickled peppers"; int max = searchMe.length(); int numPs = 0; for (int i = 0; i < max; i++) < // interested only in p's if (searchMe.charAt(i) != 'p') continue; // process p's numPs++; >System.out.println("Found " + numPs + " p's in the string."); > >
Here is the output of this program:
To see this effect more clearly, try removing the continue statement and recompiling. When you run the program again, the count will be wrong, saying that it found 35 p’s instead of 9.
A labeled continue statement skips the current iteration of an outer loop marked with the given label. The following example program, ContinueWithLabelDemo , uses nested loops to search for a substring within another string. Two nested loops are required: one to iterate over the substring and one to iterate over the string being searched. The following program, ContinueWithLabelDemo , uses the labeled form of continue to skip an iteration in the outer loop.
class ContinueWithLabelDemo < public static void main(String[] args) < String searchMe = "Look for a substring in me"; String substring = "sub"; boolean foundIt = false; int max = searchMe.length() - substring.length(); test: for (int i = 0; i > foundIt = true; break test; > System.out.println(foundIt ? "Found it" : "Didn't find it"); > >
Here is the output from this program.
The return Statement
The last of the branching statements is the return statement. The return statement exits from the current method, and control flow returns to where the method was invoked. The return statement has two forms: one that returns a value, and one that doesn’t. To return a value, simply put the value (or an expression that calculates the value) after the return keyword.
The data type of the returned value must match the type of the method’s declared return value. When a method is declared void , use the form of return that doesn’t return a value.
The Classes and Objects lesson will cover everything you need to know about writing methods.