Appearance
Control Flow Statements in Java: Decision Making, Looping, and Branching
Every program you write needs to make decisions. Should this code run or not? Should you repeat this action ten times? Should you stop early if a condition is met? These are the kinds of questions that control flow statements answer. Without them, your program would just execute every line from top to bottom with no intelligence at all.
Control flow statements in Java fall into three broad categories:
- Decision making statements like
if,if else, andswitch - Iterative statements like
for,while, anddo whileloops - Branching statements like
breakandcontinue
By the end of this article you will understand all three categories deeply, know the rules that Java enforces around them, and be prepared for the interview questions that come up around these topics constantly.
Decision Making Statements
The if Statement
Think about your morning routine. If it is raining outside, you grab an umbrella. That is an if statement in real life. You check a condition, and if that condition is true, you do something.
In Java, the structure looks like this:
java
int value = 13;
if (value > 8) {
System.out.println("Value is greater than 8");
}The condition inside the parentheses must evaluate to a boolean, either true or false. If it is true, the block of code inside the curly braces executes. If it is false, the block is skipped entirely and Java moves on to whatever comes after it.
The if else Statement
Now imagine you want to do one thing when the condition is true and a completely different thing when it is false. That is where else comes in.
java
int marks = 45;
if (marks >= 50) {
System.out.println("You passed!");
} else {
System.out.println("You failed. Try again.");
}Only one of these two blocks will ever execute for any given value of marks. They are mutually exclusive.
The if else if Ladder
What if you have more than two possible outcomes? You chain conditions together using else if. Think about a grading system:
java
int marks = 72;
if (marks >= 90) {
System.out.println("Grade: A");
} else if (marks >= 80) {
System.out.println("Grade: B");
} else if (marks >= 70) {
System.out.println("Grade: C");
} else if (marks >= 60) {
System.out.println("Grade: D");
} else {
System.out.println("Grade: F");
}Java evaluates these conditions from top to bottom. The moment one condition is true, that block executes and all the remaining conditions are skipped. This is important: even if multiple conditions could theoretically be true, only the first matching one runs.
For marks = 72, the first condition (marks >= 90) is false, the second (marks >= 80) is false, and the third (marks >= 70) is true, so "Grade: C" prints and Java jumps past the rest.
Nested if Statements
You can place an if statement inside another if statement. This is called nesting. There is no limit to how deep you can nest, though deep nesting usually signals that your logic needs to be reorganized.
java
int value = 13;
if (value > 8) {
// We are now inside the outer if block
if (value < 15) {
System.out.println("Value is greater than 8 but less than 15");
} else {
System.out.println("Value is greater than or equal to 15");
}
}Here value = 13 is greater than 8, so we enter the outer block. Inside that block, 13 is less than 15, so we enter the inner if and print the message. The inner else is skipped.
The Switch Statement
The switch statement is an alternative to a long chain of if else if conditions. It works especially well when you are comparing one variable against many specific constant values.
Think of a TV remote. You press a button (channel 1, 2, 3, etc.) and a specific action happens based on which button you pressed. That is exactly what switch does.
Basic Switch Syntax
java
int day = 3;
switch (day) {
case 1:
System.out.println("Monday");
break;
case 2:
System.out.println("Tuesday");
break;
case 3:
System.out.println("Wednesday");
break;
case 4:
System.out.println("Thursday");
break;
default:
System.out.println("Weekend or invalid day");
}Java takes the value of day (which is 3) and checks it against each case value from top to bottom. When it finds case 3, it executes that block and prints "Wednesday".
Using an Expression as the Switch Value
You are not limited to passing a simple variable. You can pass an expression:
java
int a = 1;
int b = 2;
switch (a + b) { // expression value is 3
case 1:
System.out.println("Sum is 1");
break;
case 2:
System.out.println("Sum is 2");
break;
case 3:
System.out.println("Sum is 3");
break;
default:
System.out.println("Other sum");
}Java evaluates a + b to get 3, then looks for case 3, finds it, and prints "Sum is 3".
Fall Through: One of the Most Important Switch Concepts
This is something that trips up beginners and comes up constantly in interviews. In Java, when a case matches and there is no break statement at the end of that case block, execution continues falling through into the next case block, and the next, and the next, until it either hits a break or reaches the end of the switch.
java
int value = 2;
switch (value) {
case 1:
System.out.println("Case 1");
case 2:
System.out.println("Case 2"); // matches here
case 3:
System.out.println("Case 3"); // falls through to here!
case 4:
System.out.println("Case 4"); // falls through to here!
break;
case 5:
System.out.println("Case 5");
}Output:
Case 2
Case 3
Case 4This surprises people. Java matched case 2, but because there was no break, it kept executing case 3 and case 4 as well. Case 4 has a break, so execution stops there. Case 5 never runs.
Fall through is not always a bug. Sometimes it is intentional and useful. For example, grouping months into quarters:
java
String month = "February";
switch (month) {
case "January":
case "February":
case "March":
System.out.println("Month is in Quarter 1");
break;
case "April":
case "May":
case "June":
System.out.println("Month is in Quarter 2");
break;
default:
System.out.println("Other quarter");
}Here January, February, and March all fall through to the same println statement. This is intentional grouping using fall through.
Switch Rules You Must Know
Java has strict rules about what you can and cannot use in a switch statement. These come up in every Java interview.
Allowed data types in the switch expression:
You can use exactly 10 types:
byteand its wrapperByteshortand its wrapperShortintand its wrapperIntegercharand its wrapperCharacterStringenum
Not allowed in switch expressions:
longfloatdoubleboolean
The reason long, float, and double are excluded is that switch was designed for discrete exact matching, not ranges or approximations. The reason boolean is excluded is that you only have two possible values (true/false) and an if else is cleaner and more readable for that.
Additional switch rules:
- Two cases cannot have the same value. You cannot write
case 3twice in the same switch. The compiler will reject it. - Case values must be constants or literals, not variables. You can use a literal like
case 5, or a final variable likecase MY_CONSTANT, or an enum value, but you cannot use a regular variable likecase x. - The
defaultcase is optional but highly recommended. It handles anything that does not match any case, like theelseclause in anif else ifladder. - The
defaultcase does not have to be at the bottom. You can put it anywhere in the switch. Java will still evaluate it only when no other case matches.
java
final int MAX = 100;
switch (someValue) {
case 1: // literal, allowed
break;
case MAX: // final variable, allowed (it's a compile-time constant)
break;
// case x: // regular variable, NOT allowed
}Switch Expression (Java 12 and Later)
Java 12 introduced a modernized switch that works as an expression rather than just a statement. The big difference is the arrow -> syntax, which eliminates fall through entirely and makes the code much cleaner.
Arrow Syntax
java
int day = 3;
String dayName = switch (day) {
case 1 -> "Monday";
case 2 -> "Tuesday";
case 3 -> "Wednesday";
case 4 -> "Thursday";
case 5 -> "Friday";
case 6 -> "Saturday";
case 7 -> "Sunday";
default -> "Invalid day";
};
System.out.println(dayName); // WednesdayNotice several things:
- The switch now returns a value, which you can assign to a variable.
- Each case uses
->instead of:. - There is no
breakanywhere. Fall through cannot happen with arrow syntax. - All possible cases must be handled. If you do not cover every possible value, you must include a
default.
Grouping Cases in Arrow Syntax
You can handle multiple values in one case using a comma separated list:
java
int month = 2;
String quarter = switch (month) {
case 1, 2, 3 -> "Quarter 1";
case 4, 5, 6 -> "Quarter 2";
case 7, 8, 9 -> "Quarter 3";
case 10, 11, 12 -> "Quarter 4";
default -> "Invalid month";
};
System.out.println(quarter); // Quarter 1This is cleaner than the fall through grouping of the traditional switch.
The yield Statement
With arrow syntax you cannot write multiple lines of code in a case because the arrow expects a single expression. What if you need to do some computation before returning the value? That is where yield comes in.
yield is used inside a switch expression to return a value from a block:
java
int value = 3;
String result = switch (value) {
case 1 -> "One";
case 2 -> "Two";
case 3 -> {
// You can write multiple lines here
String msg = "The value is three";
System.out.println("Computing result...");
yield msg; // yield returns the value from this block
}
default -> "Other";
};
System.out.println(result);Think of yield as the return statement specifically for switch expressions. You use it when a case needs more than one line of logic before producing its value.
Iterative Statements (Loops)
Loops let you repeat a block of code multiple times without writing it out multiple times. Imagine printing numbers from 1 to 1000. You would not write System.out.println one thousand times. A loop does it in three lines.
The for Loop
The for loop is used when you know in advance how many times you want to iterate. It has three parts in its header: initialization, condition, and update.
java
for (int i = 1; i <= 5; i++) {
System.out.println("Count: " + i);
}Output:
Count: 1
Count: 2
Count: 3
Count: 4
Count: 5How it works step by step:
int i = 1runs once at the start (initialization).i <= 5is checked. If true, the body runs. If false, the loop ends.- After the body runs,
i++executes (update). - Go back to step 2 and repeat.
You can count backwards too:
java
for (int i = 10; i >= 1; i--) {
System.out.println(i);
}The while Loop
The while loop is used when you do not know in advance how many times you will iterate. The loop continues as long as the condition is true.
java
int value = 1;
while (value <= 5) {
System.out.println(value);
value++;
}Output:
1
2
3
4
5The variable is initialized before the loop. The condition is checked at the top. The update happens inside the body. The loop stops as soon as value becomes 6, because 6 <= 5 is false.
Important: With a while loop, if the condition is false from the very beginning, the loop body never executes at all. The body runs zero times.
The do while Loop
The do while loop is the one you use when you need the loop body to execute at least once, regardless of the condition.
java
int value = 10;
do {
System.out.println("This always runs at least once: " + value);
value++;
} while (value <= 5);Output:
This always runs at least once: 10Even though 10 <= 5 is false, the body still ran once because the condition is checked at the bottom, after the first execution. This is the key difference between do while and while.
A practical use case: a menu driven program. You always want to show the menu at least once, then keep showing it as long as the user does not choose to exit.
java
Scanner scanner = new Scanner(System.in);
int choice;
do {
System.out.println("1. Play");
System.out.println("2. Settings");
System.out.println("3. Exit");
System.out.print("Enter choice: ");
choice = scanner.nextInt();
} while (choice != 3);The for each Loop (Enhanced for Loop)
The for each loop is designed specifically for iterating over arrays and collections. It is cleaner and less error prone than a traditional for loop when you just want to go through every element.
java
int[] numbers = {10, 20, 30, 40, 50};
for (int num : numbers) {
System.out.println(num);
}Read this as: "for each num in numbers, print it."
You do not manage an index variable. You do not worry about going out of bounds. You just get each element in order.
java
String[] fruits = {"Apple", "Banana", "Cherry"};
for (String fruit : fruits) {
System.out.println(fruit);
}Output:
Apple
Banana
CherryThe for each loop also works with any class that implements the Iterable interface, which includes all Java collections like ArrayList, HashSet, LinkedList, and so on.
Branching Statements
break
The break statement immediately exits the nearest enclosing loop or switch statement. Execution continues with the first statement after the loop or switch.
java
for (int value = 1; value <= 10; value++) {
if (value == 5) {
break; // stop the loop when value reaches 5
}
System.out.println(value);
}Output:
1
2
3
4When value becomes 5, the break fires and the loop ends. 5 itself is never printed because the check happens before the print statement in this example. You can rearrange the order depending on your needs.
continue
The continue statement skips the rest of the current iteration and jumps to the next one. Unlike break, it does not exit the loop. The loop keeps going.
java
for (int value = 1; value <= 10; value++) {
if (value == 3) {
continue; // skip 3, go to next iteration
}
System.out.println(value);
}Output:
1
2
4
5
6
7
8
9
10Number 3 is skipped. Everything else prints normally. The loop runs all 10 iterations, but when value == 3 the continue causes the println to be skipped for that iteration only.
break and continue in Nested Loops
When you have loops inside loops, break and continue by default affect only the innermost loop they are inside.
java
for (int i = 1; i <= 3; i++) {
for (int j = 1; j <= 3; j++) {
if (j == 2) {
break; // only breaks the inner loop
}
System.out.println("i=" + i + ", j=" + j);
}
}Output:
i=1, j=1
i=2, j=1
i=3, j=1The inner loop breaks when j == 2, but the outer loop keeps going through all three values of i. For each value of i, the inner loop runs, prints j=1, then breaks when j would become 2.
Similarly, continue in a nested loop only affects the innermost loop:
java
for (int i = 1; i <= 3; i++) {
for (int j = 1; j <= 3; j++) {
if (j == 2) {
continue; // skips j=2 in the inner loop
}
System.out.println("i=" + i + ", j=" + j);
}
}Output:
i=1, j=1
i=1, j=3
i=2, j=1
i=2, j=3
i=3, j=1
i=3, j=3j=2 is skipped for every value of i.
Labeled break: Breaking Out of Multiple Loops
What if you want to break out of the outer loop from inside a nested loop? By default break only exits the innermost loop. To break out of an outer loop you use a labeled break.
A label is an identifier followed by a colon that you place before the loop you want to target.
java
outer: // this is the label for the outer loop
for (int i = 1; i <= 3; i++) {
for (int j = 1; j <= 3; j++) {
if (i == 2 && j == 2) {
break outer; // breaks out of the outer loop
}
System.out.println("i=" + i + ", j=" + j);
}
}
System.out.println("Exited both loops");Output:
i=1, j=1
i=1, j=2
i=1, j=3
i=2, j=1
Exited both loopsWhen i==2 and j==2, the break outer does not just exit the inner loop. It exits the loop labeled outer, which is the outer for loop. Execution jumps to the line after that outer loop.
You can also use labeled continue to skip an iteration of an outer loop:
java
outer:
for (int i = 1; i <= 3; i++) {
for (int j = 1; j <= 3; j++) {
if (j == 2) {
continue outer; // skips to next iteration of outer loop
}
System.out.println("i=" + i + ", j=" + j);
}
}Output:
i=1, j=1
i=2, j=1
i=3, j=1When j == 2, instead of continuing the inner loop, continue outer skips to the next iteration of the outer loop. So j=2 and j=3 never print for any value of i.
Interview Questions and Common Pitfalls
Q: What data types are allowed in a switch statement?
The allowed types are byte, short, int, char, their corresponding wrapper classes (Byte, Short, Integer, Character), String, and enum. That gives you 10 types in total.
Not allowed: long, float, double, boolean.
Q: Can two cases in a switch have the same value?
No. The compiler will reject this. Each case value must be unique within a switch statement.
Q: What is fall through in switch and is it a bug?
Fall through means that when a case matches and there is no break at the end, execution continues into the next case block. It is not always a bug. It can be used intentionally to group multiple cases that should produce the same result. However, unintentional fall through is a very common source of bugs.
Q: What is the difference between break and continue?
break exits the loop entirely. continue skips the rest of the current iteration and moves to the next one. The loop itself continues running with continue.
Q: What is the difference between while and do while?
A while loop checks its condition before executing the body. If the condition is false from the start, the body never runs. A do while loop executes the body first and checks the condition afterward. The body always runs at least once.
Q: When should you use switch instead of if else if?
Use switch when you are comparing a single variable or expression against a set of specific constant values. Switch is often cleaner and more readable in that scenario. Use if else if when you have range based conditions or conditions involving multiple variables.
Q: What is the yield statement in switch expressions?
yield is used inside a switch expression when a case block needs multiple lines of code before producing a value. It is like return but specifically for switch expressions. You cannot use return here because you might not be returning from the method, just providing a value for the switch expression.
Q: What is the difference between a switch statement and a switch expression?
A switch statement executes a block of code. A switch expression (introduced in Java 12) returns a value and can be assigned to a variable. Switch expressions use the -> arrow syntax, eliminate fall through, and require exhaustive handling of all cases (all values must be covered or a default must be present).
Q: What does labeled break do?
Labeled break lets you break out of an outer loop from inside a nested loop. You put a label before the outer loop and reference that label in your break statement. Without a label, break only exits the innermost enclosing loop.
Q: Can the default case appear anywhere in a switch?
Yes. The default case does not have to be at the bottom. It can be placed anywhere in the switch block. Java will only execute it when no other case matches.
Putting It All Together
Here is a program that uses several of these concepts together:
java
public class ControlFlowDemo {
public static void main(String[] args) {
// if-else-if ladder
int score = 78;
if (score >= 90) {
System.out.println("Excellent");
} else if (score >= 75) {
System.out.println("Good"); // this prints
} else if (score >= 50) {
System.out.println("Average");
} else {
System.out.println("Below average");
}
// switch expression (Java 12+)
int month = 4;
String season = switch (month) {
case 12, 1, 2 -> "Winter";
case 3, 4, 5 -> "Spring"; // matches here
case 6, 7, 8 -> "Summer";
case 9, 10, 11 -> "Autumn";
default -> "Unknown";
};
System.out.println("Season: " + season); // Season: Spring
// for loop with break
System.out.println("Searching for 7:");
for (int i = 1; i <= 10; i++) {
if (i == 7) {
System.out.println("Found 7!");
break;
}
}
// for-each with continue (skip even numbers)
int[] nums = {1, 2, 3, 4, 5, 6, 7, 8};
System.out.println("Odd numbers:");
for (int n : nums) {
if (n % 2 == 0) {
continue; // skip even numbers
}
System.out.print(n + " ");
}
System.out.println();
// labeled break to exit nested loops
System.out.println("Labeled break demo:");
outer:
for (int i = 0; i < 5; i++) {
for (int j = 0; j < 5; j++) {
if (i * j > 6) {
System.out.println("Breaking at i=" + i + ", j=" + j);
break outer;
}
}
}
}
}Summary
Control flow is the backbone of any non trivial program. Here is a quick recap of everything covered:
| Concept | Key Point |
|---|---|
if / else if / else | Evaluate conditions top to bottom, first match wins |
Nested if | Place if inside if, no depth limit but keep it readable |
switch statement | Compare one value against constants, uses fall through by default |
| Fall through | Without break, execution flows into next case, intentional or not |
| Switch allowed types | byte, short, int, char, their wrappers, String, enum. Not long, float, double, boolean |
| Switch expression (Java 12) | Arrow syntax, no fall through, returns a value, exhaustive by requirement |
yield | Returns a value from a multi line case block in a switch expression |
for loop | Use when iteration count is known in advance |
while loop | Use when iteration count is not known, condition checked first |
do while loop | Body always runs at least once, condition checked after |
for each loop | Clean iteration over arrays and collections without index management |
break | Exits the innermost loop or switch entirely |
continue | Skips the current iteration, loop continues |
Labeled break | Exits a specific outer loop by name |
Labeled continue | Skips to next iteration of a specific outer loop |
Master these building blocks and you will be able to express any logic your programs need. They form the foundation that everything else in Java is built upon.