// Java Fundamentals · Lesson 04
Control Flow Statements
So far every program ran from top to bottom, every line exactly once. Now your program makes decisions: it checks a condition and chooses which lines run.
BY THE END OF THIS LESSON YOU CAN
- Read and draw a flowchart of a decision
- Write
if,elseandelse ifchains and nested ifs, without the classic traps - Pick a value with the ternary operator
?: - Write
switchstatements, classic withbreakand the arrow form, and switch expressions withyield - Choose between
if,switchand?:for a problem
Part 1 of 7
Making decisions with if
A condition is a question with a yes or no answer. if runs a block of code only when the answer is yes.
// 1.1
A straight line or a fork in the road
A flowchart draws a program as shapes and arrows. Until now your programs were a straight line. A decision adds a fork: the program takes one path or the other, never both.
booleanSequential
every step runs onceEach step runs once, in order. This is every program you have written so far.
Branching: an ATM
// 1.2
Anatomy of an if
An if statement runs its block only when the condition is true. When it is false, Java skips the block and carries on after the }. Click any part.
if (balance >= amount) { balance = balance - amount; }
Start with the condition: its value must be true or false.
int balance = 120;
int amount = 50;
if (balance >= amount) {
balance = balance - amount;
}
System.out.println(balance);
$ java Main 70
Java is stricter than C
In C and JavaScript, if (count) means “if count is not zero”. In Java the condition must be a boolean. A number is not a yes or no answer, so this doesn’t compile.
Say what you mean: if (count > 0). The same goes for if (1): it doesn’t compile either.
public class Main {
public static void main(String[] args) {
int count = 3;
if (count) {
System.out.println("You have messages");
}
}
}
$ javac Main.java Main.java:4: error: incompatible types: int cannot be converted to boolean if (count) { ^ 1 error
// 1.3
Braces are optional. Write them anyway.
Without { }, an if controls only the one statement right after it. Indentation means nothing to Java. Run the code, then add the braces.
Rule for this course: always write the braces, even for one line. IntelliJ’s Reformat Code (Ctrl+Alt+L, on a Mac ⌘+⌥+L) fixes the indentation, and then this bug is easy to see.
// Apple, February 2014 · CVE-2014-1266
“goto fail”: one extra line broke secure connections
Apple’s code for secure connections (TLS, the “S” in HTTPS) is written in C, which has the same rule about braces. One line was accidentally duplicated:
The marked goto fail; looks like part of the if above it, but it isn’t. It always runs and jumps past the last step, the check of the server’s signature. err still held 0, meaning “no error”, so the connection was accepted. Anyone on the same Wi-Fi could pretend to be your bank. Apple fixed it in iOS 7.0.6 and OS X 10.9.2.
// 1.4
if and else: exactly one of two
Add an else block and the program always does one of two things: never both, and never neither. Pick a scenario and step through it like a debugger.
Memory
// 1.5
Writing good conditions
A condition is any expression whose value is a boolean. Everything from lesson 3 works here: comparisons, &&, ||, ! and .equals.
Give a long condition a name
Store it in a boolean with a clear name. The if then reads like a sentence. Change the values:
Combine with && and ||
if (age >= 18 && hasTicket) {
System.out.println("Come in");
}
if (day == 6 || day == 7) {
System.out.println("Weekend");
}Compare Strings with .equals
if (city.equals("Baku")) {
System.out.println("Capital");
}== checks whether two variables point to the same String object, not whether the text is the same. Part 2 shows the trap.
Don’t compare a boolean with true
if (isActive == true)if (isActive)
if (isActive == false)if (!isActive)
A boolean already is true or false. Comparing it with true adds nothing, and one missing = turns it into a bug (Part 2).
// 1.6
Checkpoint: making decisions
Eight quick questions on Part 1. Pick an answer to see why it is right or wrong.
Part 2 of 7
Chains, nesting and traps
Real decisions have more than two outcomes. Chain conditions, put one if inside another, and learn the traps that catch every beginner.
// 2.1
else if: the first true condition wins
Java checks the conditions from top to bottom and runs the block of the first one that is true. The conditions below it are not even checked. Move the slider, then try the other versions.
VERSION
// 2.2
Nested ifs: a login check
An if can sit inside another if. Here a login passes three checks in order. Flip the facts, then compare three ways to write the same logic.
// 2.3
The dangling else: indentation lies
Nested ifs without braces raise a question: which if does the else belong to? Java’s rule: an else belongs to the nearest if above it that has no else yet. Indentation has no say.
Read the colors
An if and the else that belongs to it get the same color. In As written, the colors show what the indentation suggests. Switch to As Java reads it to see the truth.
// 2.4
Seven classic traps
Two of these don’t compile. The dangerous ones compile fine and quietly do the wrong thing. Pick a trap to see what really happens and how to fix it.
// 2.5
Game: which line prints?
Fourteen short programs. Read the code, predict the exact output and pick it. Every answer was checked with Java 25.
// 2.6
Checkpoint: chains, nesting and traps
Eight questions on Part 2. Several of them hide one of the traps.
Part 3 of 7
The ternary operator ?:
Sometimes you don’t want to do something, you just want to pick a value. Java’s only operator with three operands does exactly that.
// 3.1
An if that gives you a value
condition ? valueIfTrue : valueIfFalse. If the condition is true, the whole expression becomes the first value, otherwise the second. It has three operands, so it is called the ternary operator. Click any part.
String status = age >= 18 ? "adult" : "minor";
if does something
It runs a block or skips it. It has no value, so you can’t write String s = if (…).
?: is something
It has a value and a type, so it fits anywhere a value fits: after =, inside println(…), in a + chain.
// 3.2
From if/else to ?:
When both branches only choose a value for the same thing, a ternary says it in one line. Pick an example and morph it. The colors show which part goes where.
// 3.3
Rules and traps of ?:
The ternary is small, but it follows strict rules. Pick a rule to see what goes wrong and how to write it instead.
// 3.4
Game: pick the ternary
Each round gives you an if/else or a task. Pick the one ternary that does exactly the same. The wrong ones swap the branches, flip the condition, get the type wrong or forget the brackets.
// 3.5
Checkpoint: the ternary operator
Eight questions on Part 3.
Part 4 of 7
The switch statement
When one variable is compared with many fixed values, switch is cleaner than a long else if chain. It also has a famous trap.
// 4.1
Anatomy of a switch
A switch looks at one value, jumps straight to the case with the same value, and runs from there. Click any part, and change day to see which lines run.
When a switch fits
One variable, compared for equality with many fixed values: a menu option, a day number, a command, a grade letter. It replaces a chain like if (day == 1) … else if (day == 2) … and says “pick one of these” more clearly.
// 4.2
What can you switch on?
The value in switch (…) is called the selector. Only some types are allowed. Try each one.
Selector types
- allowed
intshortbytechar, their wrappers (Integer…),String, and enums (a later lesson) - not allowed
longfloatdoubleboolean
// 4.3
case labels: fixed values, each one once
javac decides where each case jumps to before the program runs, so a label must be a value it already knows. Try the three versions.
What a label can be
- A literal of the selector’s type:
case 1:,case 'A':,case "Baku": - A
finalconstant:final int SATURDAY = 6;thencase SATURDAY: - Not a normal variable, not a range like
>= 90, and never the same value twice
// 4.4
Fall-through lab
A switch jumps in at the matching case, then runs line after line, straight through the next case labels. Only break gets you out. Remove some breaks and press Run.
// 4.5
Fall-through on purpose, and other selectors
Fall-through is not always a bug. Stack labels to share one block. Then switch on text and characters, and see the one value a switch can’t handle.
// 4.6
Checkpoint: the switch statement
Eight questions on Part 4. Watch out for missing breaks.
Part 5 of 7
Modern switch
Arrow labels and switch expressions, standard since Java 14, remove the fall-through trap and let a switch produce a value.
// 5.1
Arrow labels: no fall-through, no break
Write case … -> instead of case …: and a case runs only its own code. There is nothing to fall through and no break to forget. Same logic, two forms:
Rules of the arrow form
- The code after
->runs, then the switch is finished. No fall-through. - Several values share a case:
case 6, 7 ->, separated by commas. - One statement after the arrow, or a block
{ … }for several. - Don’t mix the forms:
->and:in one switch is a compile error.
Several statements? Use a block
int day = 6;
switch (day) {
case 6, 7 -> {
System.out.println("Weekend");
System.out.println("Open at 10");
}
default -> System.out.println("Open at 9");
}
$ java Main Weekend Open at 10
// 5.2
Switch expressions: a switch with a value
Put a switch after = and it becomes an expression, like the ternary: every case gives a value. It must give a value for every possible input, and the statement ends with ; after the }.
yield: the value of a block
When a case needs a block { … }, yield gives the value of the block. Think of it as “this is the answer”.
int day = 6;
int hours = switch (day) {
case 6, 7 -> {
System.out.println("Weekend!");
yield 0;
}
default -> 8;
};
System.out.println("Work hours: " + hours);
$ java Main Weekend! Work hours: 0
The classic form works too
With colons, every path needs its own yield, and fall-through still exists. Prefer arrows.
int day = 2;
int hours = switch (day) {
case 6:
case 7:
yield 0;
default:
yield 8;
};
System.out.println(hours);
$ java Main 8
// 5.3
if, switch or ?:?
All three make decisions, and each is best at a different job. Read the table, then sort eleven real tasks.
| Use | When you want to… | Example |
|---|---|---|
?: | choose between two values | a > b ? a : b |
if | test ranges or combined conditions, or do something only sometimes | score >= 90 && !late |
switch | compare one variable with many fixed values | case 1, 2, 3 -> |
A switch can’t test a range: there is no case >= 90, because labels are fixed values. In new code, prefer arrow labels and switch expressions to the classic form.
// 5.4
Game: what does this switch print?
Twelve switches: classic and arrow, statements and expressions. Some fall through, some don’t. Every answer was checked with Java 25.
// 5.5
Checkpoint: modern switch
Eight questions on Part 5.
Part 6 of 7
Putting it together
One small program that uses everything from this lesson, and the compiler errors you will meet most often.
// 6.1
Mini-program: a cinema ticket
A switch expression picks the base price, an else if chain applies the age rules, and a ternary handles the student discount. Change the customer and watch which lines run.
- Base price: Monday to Friday 8 AZN, Saturday and Sunday 12 AZN
- Children under 12 pay half
- Seniors aged 65 or more pay 3 AZN less
- Students (everyone else) pay 2 AZN less
WHAT HAPPENED
// 6.2
Break it on purpose
These are the mistakes you will make this week. Most of them javac catches for you, with the exact messages below. The last one compiles and is simply wrong. Pick a mistake to see the error and the fix.
// 6.3
Checkpoint: putting it together
Eight questions that mix the whole lesson: the cinema program, compiler errors and one logic bug.
Part 7 of 7
Wrap-up
What to remember, a final quiz, your homework and a look at the next lesson.
// 7.1
Key takeaways
A condition is a
booleanexpression. A number is not a condition:if (count)doesn’t compile.ifruns its block when the condition is true,elsewhen it is false. Exactly one of the two runs.In an
else ifchain the first true condition wins and the rest are not checked. Put the most specific condition first.Always write braces. Without them an
ifcontrols one statement, anelsebinds to the nearestif, and a stray;becomes the whole body.Compare Strings with
.equals, writeif (isActive)instead of== true, and never use=where you mean==.?:picks one of two values. It is an expression: use it where a value goes, not to run code.A classic
switchfalls through from case to case until abreak. Arrow labels->never fall through.A switch expression gives a value, must cover every input (usually with
default) and usesyieldinside a block.
// 7.2
Check yourself
Twenty questions on the whole lesson. You see the answer right after you pick.
Your checkpoints
// 7.3
Homework
You don’t know how to read input from the keyboard yet, so put the input in variables at the top of main, run the program, change the values and run it again. Tick items as you finish them. Your ticks are saved in this browser only.
// 7.4
Questions?
Next lesson: Loops and Iteration. for, while and do-while repeat code, and break and continue steer a loop. You already know break from the switch.
for (int i = 1; i <= 5; i++) {
System.out.println(i % 2 == 0 ? i + " is even" : i + " is odd");
}
$ java Main 1 is odd 2 is even 3 is odd 4 is even 5 is odd