So far every program has run top to bottom, each line exactly once. That is enough to compute a single answer, but real programs must decide — charge this customer or that one — and repeat — process every row in a file. Java gives you the same three tools as most languages: if/else for decisions, for/while for repetition, and switch for choosing one branch from many fixed values. Mastering control flow is mostly about predicting exactly which lines run, and how many times each one runs.
Choosing a branch with if
An if tests a boolean condition in parentheses. Chain conditions with else if, and catch everything left over with a final else. Java evaluates them top to bottom and runs the first branch whose condition is true, then skips the rest — so arrange conditions from most specific to most general. Put >= 90 before >= 80, or a score of 95 would wrongly match the broader check first. The condition must yield true or false; a bare number will not compile, unlike in some other languages.
flowchart TD S["if (score >= 90)"] -->|true| A["grade = A"] S -->|false| E["else if (score >= 80)"] E -->|true| B["grade = B"] E -->|false| L["else"] L --> C["grade = C"] style S fill:#c2410c,color:#fff style E fill:#c2410c,color:#fff
for: start, stop, step on one line
A counted for loop bundles three things into one header. for (int i = 1; i <= 4; i++) means: start i at 1, keep going while i <= 4, and step by adding 1 each pass, so the body runs for 1, 2, 3, 4. Swap <= for < and you get one fewer pass — the classic off-by-one. The step i++ is shorthand for i = i + 1, and i-- counts down. Everything inside the parentheses is ordinary Java, evaluated in that start, test, step order every time around.
flowchart LR
I["init: i = 1"] --> T{"i <= 4 ?"}
T -->|yes| BODY["body runs, then i++"]
BODY --> T
T -->|no| D["loop ends"]
style T fill:#c2410c,color:#fff
public class Main {
public static void main(String[] args) {
int score = 82;
String grade;
if (score >= 90) {
grade = "A";
} else if (score >= 80) {
grade = "B";
} else {
grade = "C";
}
System.out.println("Grade: " + grade);
int[] scores = {91, 78, 85};
int total = 0;
for (int s : scores) {
total = total + s;
}
System.out.println("Total: " + total);
int day = 3;
switch (day) {
case 1: System.out.println("Monday"); break;
case 3: System.out.println("Wednesday"); break;
default: System.out.println("Other");
}
}
}
switch: pick from fixed values
When you branch on one value against a list of known constants, a switch reads more cleanly than a chain of else if. Each case compares for equality; default catches anything unmatched. The catch is sharp: without a break, execution falls through into the next case and keeps going. Sometimes that is deliberate — stacking several cases in front of one shared block — but usually a missing break is a bug. Modern Java also allows switch as an expression with ->, which does not fall through; this course uses the classic form.
flowchart TD M["case 2: print(Tue)"] -->|break| S["exit switch"] N["case 3: print(Wed)"] -->|no break| F["falls into next case<br/>(keeps running)"] style S fill:#3776ab,color:#fff style F fill:#b45309,color:#fff
Looping over every element
When you want all the items and do not care about the index, the for-each form is cleaner and safer: for (int s : scores) runs once per element of the array, binding s to each value in turn. Because there is no index to manage, there is no off-by-one and no chance of reading past the end. For-each works over arrays and every Collection; reach for it by default, and reserve the counted for for the cases where you genuinely need the position.
while: repeat until a condition flips
A while loop runs its body over and over as long as its condition stays true. It is the right tool when you do not know in advance how many passes you need — keep doubling until you pass 100. The responsibility it hands you is sharp: the body must change something the condition reads, or the loop runs forever. A counted for makes that obligation explicit in its header; a while leaves it entirely to you, which is exactly why accidental infinite loops live here.
public class Main {
public static void main(String[] args) {
int total = 0;
for (int i = 1; i <= 10; i++) {
if (i % 2 == 0) {
continue; // skip even numbers
}
total += i; // add only the odds
}
System.out.println("odd sum 1..10: " + total);
int n = 1;
int count = 0;
while (n < 100) {
n *= 2;
count++;
}
System.out.println("doublings to pass 100: " + count);
System.out.println("n landed at: " + n);
}
}
break and continue
Two keywords bend a loop's flow. break abandons the loop entirely — handy for search loops that should stop the instant they find a match. continue skips the rest of the current pass and jumps to the next one — handy for filtering, as in add up only the odd numbers. Both are tools rather than crutches: a loop studded with continue is often clearer rewritten as an if/else, and a break buried three levels deep is usually a sign the logic wants restructuring.
How many times does for (int i = 0; i < 5; i++) run its body?
i takes the values 0, 1, 2, 3, 4 — five of them. The condition i < 5 is true for each and stops when i reaches 5. Using < rather than <= is exactly what makes this five passes instead of six.
What does this program print? Read it carefully and type the exact output (three lines).
public class Main {
public static void main(String[] args) {
int sum = 0;
for (int i = 1; i <= 4; i++) {
sum = sum + i;
}
System.out.println("Sum 1..4 = " + sum);
int score = 82;
if (score >= 90) {
System.out.println("A");
} else if (score >= 80) {
System.out.println("B");
} else {
System.out.println("C");
}
int half = 5 / 2;
System.out.println("5 / 2 = " + half);
}
}
The loop adds 1 + 2 + 3 + 4, which is
10.82is not>= 90, but it is>= 80, so the middle branch runs.5 / 2uses integer division — the fraction is dropped, giving2.
Loops, break, and division. Predict all four lines — watch the loop bounds and the integer maths.
public class Main {
public static void main(String[] args) {
int sum = 0;
for (int i = 0; i < 5; i++) {
sum += i;
}
System.out.println("sum: " + sum);
int firstBig = -1;
for (int n = 1; n <= 20; n++) {
if (n * n > 50) {
firstBig = n;
break;
}
}
System.out.println("first n with n*n > 50: " + firstBig);
int a = 10;
int b = 3;
System.out.println("10 / 3 = " + a / b);
System.out.println("10 % 3 = " + a % b);
}
}
i < 5runs for 0, 1, 2, 3, 4 — and 0+1+2+3+4 is10.7*7is 49 (not over 50) but8*8is 64, sobreakstops the search at8.Integer division gives
10 / 3 = 3, and modulo gives the remainder10 % 3 = 1.
In a switch, what happens when a matching case has no break statement?
Without break, Java falls through to the next case. Sometimes that's intentional, but usually it's a bug — which is why most cases end with break.
If x is an int, what is wrong with if (x = 5) { ... }?
= is assignment and == is comparison. if (x = 5) tries to use the int value 5 as a boolean condition, which Java rejects at compile time. In C the same line would quietly assign and treat the result as true; Java's strictness is the protection.
Recap
if/else if/elseruns the first true branch; order conditions specific to general.for (init; condition; step)runs a counted number of times — mind the<vs<=off-by-one.whilerepeats until its condition flips; the body must eventually make it false.switchmatches a value againstcases; withoutbreak, it falls through.=assigns,==compares, and integer division drops the fraction while%keeps the remainder.
Next you will bundle data and the actions on it into classes and objects.