control flow
if, loops, break, continue, and labeled breaks (yes, java has those).
- chapter
- chapter 02.06
- reading time
- 6 min read
code runs top to bottom until something says otherwise. if picks a branch, loops (while, do, for, for-each) repeat, and break / continue jump out of or ahead in a loop. java also has labeled breaks, for jumping out of nested loops in one go.
the picture
think of a program as a recipe. by default you do step 1, then step 2, then step 3. control flow is the "if the dough is sticky, add flour" and the "stir until smooth" bits: the steps that decide which step comes next.
every one of these statements is built on a condition: an expression that's a boolean. not a number, not "something truthy". exactly true or false.
int x = 5;
if (x = 5) IO.println("five");error: incompatible types: int cannot be converted to boolean. in C that line compiles and is a classic bug (it assigns). java refuses, because if only accepts booleans. you meant x == 5.
if, else if, else
void main() {
int score = 72;
if (score >= 90) {
IO.println("A");
} else if (score >= 70) {
IO.println("B");
} else {
IO.println("C");
}
}B
conditions are checked top to bottom, and the first true one wins. everything after it is skipped, even if it would also be true. so order matters: put score >= 70 first and nobody ever gets an A.
braces are optional for a single statement. use them anyway: the day someone adds a second line under an unbraced if, it silently runs every time.
the for loop, in slow motion
a for loop packs four things into one line, and they do not run left to right:
int sum = 0;for (int i = 0; i < 3; i++) {sum += i;}IO.println(sum); // 3
init runs exactly once, before anything else. i is born here, and it only exists inside the loop.
for (init; check; update): init once, then check → body → update, over and over, until the check is false. use it when you're counting. the variable declared in init (i) only exists inside the loop.
while and do-while
while is the loop for "until something happens", when you can't know the count up front:
- 1void main() {
- 2 int n = 6;
- 3 int steps = 0;
- 4 while (n != 1) {
- 5 if (n % 2 == 0) {
- 6 n = n / 2;
- 7 } else {
- 8 n = 3 * n + 1;
- 9 }
- 10 steps++;
- 11 }
- 12 IO.println(n + " after " + steps + " steps");
- 13}
·main starts.
do { ... } while (check); is the same loop with the check moved to the bottom, so the body always runs at least once. it's rare, mostly for "ask until the input is valid".
void main() {
int n = 10;
while (n < 5) { IO.println("while " + n); n++; }
do { IO.println("do " + n); n++; } while (n < 5);
}do 10
the while checks first, sees 10 < 5 is false, and never runs. the do runs once, then checks.
for going through every element of an array or a collection, there's the for-each loop: for (int x : xs) { ... }. no index, no off-by-one. it's the one you'll use most once you meet arrays.
break, continue, and labels
break leaves the loop it's in. continue skips the rest of the current round and goes to the next one (in a for, that means the update runs next). in nested loops, both only affect the innermost loop, unless you give a loop a label and name it.
outer:for (int i = 0; i < 4; i++) {for (int j = 0; j < 4; j++) {if (i == 1 && j == 2) break;IO.print(i + "" + j + " ");}IO.print("| ");}IO.println("done");
break leaves the innermost loop only. row 1 stops early, but its "|" still prints and the outer loop carries on with row 2.
i == 1 && j == 2. pick the jump and compare the grid and the real output. the label outer: names the outer loop so a jump from the inner loop can target it.labeled breaks are rare, and that's fine. when you need to stop searching a 2d grid the moment you find something, break outer is clearer than a found flag checked in two places. (pulling the loops into a method and using return is often clearer still.)
for (int i = 0; i < 3; i++); {
IO.println("hi");
}- conditions must be real
booleans.if (x = 5)doesn't compile in java. if / else if / else: the first true branch wins, the rest are skipped.forruns init once, then check → body → update until the check is false.whilechecks first,do-whileruns once then checks.breakandcontinueaffect the innermost loop. label a loop to target it from inside.