Java Break vs Continue: Labelled Break for Nested Loops
In Java, break leaves the innermost loop or switch and continue skips to the next iteration. How labels exit nested loops, and when return is cleaner.
- Course: Java study plan
- Module: Control flow
- Kind: Lesson
- Reading time: 11 min
- Runtime: OpenJDK 18
What is the difference between break and continue in Java?
In Java, break exits the innermost enclosing loop or switch immediately, while continue abandons only the current iteration and moves on to the next one; in a for loop, the update step runs first. Both affect only the innermost loop unless given a label, as in break outer;, which leaves the labelled outer loop as well.
Lesson
A loop's condition says when to stop between iterations. Real loops often need to stop or skip in the middle — a match found, a bad record to ignore, an inner loop that should end the outer one too. Java gives four tools: break, continue, labelled versions of both, and return. Each has a precise meaning, and using the wrong one is a common source of subtle bugs.
break: leave the loop now
int found = -1;
for (int i = 0; i < arr.length; i++) {
if (arr[i] == target) {
found = i;
break; // stop scanning; the rest of the array is not examined
}
}
break exits the innermost enclosing loop or switch immediately; execution continues with the statement after it. It is the standard way to stop a search on the first hit, and the standard way out of while (true).
Inside a switch that is inside a loop, break leaves the switch, not the loop — a frequent surprise:
while (running) {
switch (cmd) {
case "quit" -> { running = false; } // break here would only leave the switch
default -> handle(cmd);
}
}
continue: skip to the next iteration
for (String line : lines) {
if (line.isBlank()) continue; // skip blank lines
if (line.startsWith("#")) continue; // and comments
process(line);
}
continue abandons the rest of the current iteration and goes to the next: in a for, the update runs and then the condition is checked; in a while, the condition is checked. It is the loop equivalent of a guard clause — filters at the top, the real work below, no nesting.
A continue in a while loop whose increment is at the bottom of the body skips the increment and loops forever:
int i = 0;
while (i < n) {
if (skip(i)) continue; // i is never incremented → infinite loop
work(i);
i++;
}
This is one concrete reason to prefer for when there is an update step.
Labels: breaking out of nested loops
break and continue reach only the innermost loop. To leave an outer loop from inside an inner one, label the outer loop:
outer:
for (int r = 0; r < rows; r++) {
for (int c = 0; c < cols; c++) {
if (grid[r][c] == target) {
System.out.println("found at " + r + "," + c);
break outer; // leaves BOTH loops
}
}
}
next:
for (int[] row : rows) {
for (int v : row) {
if (v < 0) continue next; // abandon this row, go to the next
}
System.out.println("row is all non-negative");
}
A label is an identifier followed by a colon, placed before a statement (normally a loop). break label exits the labelled statement; continue label goes to the next iteration of the labelled loop. Labels are not goto — you can only break out of an enclosing labelled statement, never jump into one.
Labels are legitimate and clearer than a found flag checked in every loop condition. But if a nested loop needs one, consider extracting the inner search into a method and using return — usually the cleanest answer.
return: leave the method
static int indexOf(int[] arr, int target) {
for (int i = 0; i < arr.length; i++) {
if (arr[i] == target) return i; // leaves the loop AND the method
}
return -1;
}
return inside a loop ends the whole method, loop included. For a search that lives in its own method this beats break plus a result variable: no flag, no state, the answer is returned where it is found. The -1 after the loop is the "not found" path and the compiler insists on it (every path must return).
Extracting loops into small methods that return early is one of the highest-leverage refactorings: findFirstNegative, containsDuplicate, allPositive each become a five-line method with an early return instead of a flag.
break in switch (classic form)
In the colon form, break ends the case; without it, execution falls through. In the arrow form there is nothing to break out of, and a break inside an arrow-case block that is inside a loop does break the loop — since there is no fall-through to stop, the switch is not what break targets… except it is: a break in an arrow switch statement still targets the switch. Use a labelled break or a flag when you need to leave a loop from inside any switch.
Flags versus early exits
boolean found = false;
for (int i = 0; i < n && !found; i++) {
if (match(i)) found = true;
}
The flag-in-the-condition style works but spreads the exit logic across two places. break (or return from a method) says the same thing in one. Prefer the early exit; use a flag only when you need to remember the outcome after the loop and the loop must also finish for other reasons.
Unreachable code
for (…) {
break;
System.out.println("never"); // compile error: unreachable statement
}
Java refuses to compile statements it can prove unreachable — after break, continue, return, throw, or inside while (false). (if (false) is exempt, for conditional compilation.) A return in both branches of an if/else followed by more code is the usual way to meet this error.
Interview angle
- "How do you exit two nested loops?" A labelled
break, or move the loops into a method andreturn. - "What does
breakdo inside aswitchinside a loop?" Leaves the switch only. - "Difference between
breakandcontinue?"breakleaves the loop;continueskips to the next iteration. - "Does Java have
goto?" It is a reserved word but not implemented; labelled break/continue are the structured alternative.
Key takeaways
breakleaves the innermost loop or switch;continueskips to the next iteration (running afor's update).- Labels let
break/continuetarget an outer loop; extraction into a method withreturnis often cleaner. continuein awhilewith a bottom increment loops forever.- The compiler rejects unreachable statements — a signal that the control flow is not what you think.
Common questions
How do I break out of nested loops in Java?
Label the outer loop, as in outer: for (…), and write break outer; inside the inner loop; it leaves both loops at once. Often cleaner still is moving the loops into their own method and using return as soon as the result is found.
Does break inside a switch exit the loop in Java?
No. A break inside a switch that sits inside a loop leaves only the switch, and the loop carries on. To leave the loop from there, use a labelled break, set a flag the loop condition checks, or return from the method.
Does Java have goto?
No. goto is a reserved word in Java but is not implemented, so it cannot be used. Labelled break and continue are the structured alternative: they can leave an enclosing labelled statement but never jump into one.
Why does continue cause an infinite loop in a while loop?
If the increment sits at the bottom of the while body, a continue above it jumps straight back to the condition without incrementing, so the same value is tested forever. A for loop avoids this, because continue still runs its update step.
What does "unreachable statement" mean in Java?
The compiler has proved that a statement can never run, such as code directly after break, continue, return or throw in the same block, or inside while (false), and it refuses to compile it. if (false) is exempt, so it can still be used for conditional compilation.
Exercises
Read until END
Read lines until a line that is exactly END (or until input runs out). Skip blank lines and lines that start with # (after trimming). Print every other line numbered from 1 as <k>: <line>, then a final line skipped=<count of skipped lines>.
Use break for END and continue for the skipped lines.
Example input:
alpha
# comment
beta
END
gamma
Output:
1: alpha
2: beta
skipped=2First repeat in a grid
Read r and c and an r × c grid of integers. Scanning row by row, left to right, find the first cell whose value has already appeared and print repeat <value> at (<row>,<col>) (0-based), leaving both loops with a labelled break the moment it is found; print none if every value is distinct. Then print scanned=<how many cells were examined>.
Example: 2 3 then 1 2 3 / 4 2 5 →
repeat 2 at (1,1)
scanned=5In this module: Control flow
← Loops — while, do-while, for and for-each · Loop patterns every program is made of →