Control flow determines which statements run and how often. Methods give a repeated operation a name, inputs and an optional result. In Java, ordinary functions belong to classes and are called methods. This lesson uses Java 21 and keeps methods static so you can focus on behavior before introducing objects.
Choose branches and loops deliberately
An if condition must be a boolean. Use else if for mutually exclusive alternatives and else for the remaining case. Always use braces, even around one statement: adding a second statement later should not silently change its meaning.
&& and || short-circuit: they evaluate the right operand only when needed. In name != null && !name.isBlank(), the null check protects the method call. A single & on booleans evaluates both operands and does not provide that protection.
A for loop makes initialization, continuation and advancement visible together. Use while when continuation depends on a changing condition, and do/while when the body must execute at least once. An enhanced for loop visits array or collection values without exposing an index. break exits the nearest loop; continue skips to its next iteration. Nested loops need particular care because these statements do not automatically affect every surrounding loop.
Build a small report
Save as ProgressReport.java. Compile with javac --release 21 ProgressReport.java, then run java ProgressReport.
public class ProgressReport {
static String band(int score) {
if (score < 0 || score > 100) {
throw new IllegalArgumentException("score must be 0 to 100");
}
if (score >= 80) {
return "strong";
}
return score >= 50 ? "developing" : "practice";
}
static int sumTo(int limit) {
int total = 0;
for (int number = 1; number <= limit; number++) {
total += number;
}
return total;
}
static String nextAction(String band) {
return switch (band) {
case "strong" -> "Try a project";
case "developing" -> "Review the exercises";
default -> "Repeat the basics";
};
}
public static void main(String[] args) {
for (int score : new int[] {49, 50, 80}) {
String result = band(score);
System.out.println(score + ": " + nextAction(result));
}
System.out.println("sum: " + sumTo(4));
}
}
Expected output:
49: Repeat the basics
50: Review the exercises
80: Try a project
sum: 10
Read band from top to bottom. It rejects invalid inputs, handles the highest range, then chooses between the two remaining ranges. An early return ends the method, not merely the current branch. The exception deliberately signals an invalid request; a later lesson explains how callers handle it.
The switch expression produces a value. Arrow cases do not fall through to the next case. Every possible path must produce a value or throw, which is why this string switch includes default. A multi-statement case can use a block and yield its value. A null selector is not handled by this example's default case; its caller supplies a non-null result from band.
Understand method boundaries
int sumTo(int limit) declares a return type, method name and parameter. Calling sumTo(4) evaluates the argument and assigns its value to the parameter. A void method performs an action without returning a value. Keep a method focused on one operation, and prefer returning data over printing inside every helper.
Java always passes arguments by value. For primitives, the copied value is the number or boolean. For objects, it is the reference. A method can mutate an array reached through that copied reference, but assigning the parameter to a new array does not replace the caller's variable.
A variable declared inside a block is visible only within its scope. Avoid reusing short names for unrelated purposes. Overloading allows methods with the same name and different parameter lists; the return type alone cannot distinguish overloads. Recursion means calling the same method again: it needs a stopping condition, and very deep recursion can exhaust the call stack. A loop is simpler for this sum.
Pitfalls and exercise
An accidental semicolon after if or for creates an empty statement. Loop conditions using <= array.length run one step too far. A loop also needs measurable progress toward stopping. Our sumTo is intentionally for small nonnegative limits; large inputs need range checks and wider or exact arithmetic.
Add countPassing(int[] scores) that counts scores of at least 50 while rejecting invalid scores. Test an empty array and the values 49, 50 and 100. Then add a negative value and confirm failure.
For the solution, initialize a counter to zero, visit each score, validate it using the same bounds as band, and increment when the threshold is met. Return the counter after the loop. The boundary tests should produce 0 and 2; do not return from inside the loop after seeing only the first value.
Official references
Previous: Variables and Types. Next: Arrays and Strings.

