Making decisions with if
On This Lesson 11 topics
Lesson Overview
Until now every program you wrote ran its statements from top to bottom, every time, in the same order. Real programs must react: a withdrawal is refused when the balance is too low, a discount applies only to members, an error message appears only when the input is wrong.
The tool for this is the if statement. It asks a yes-or-no question and runs a block of code only when the answer is yes. Think of a road junction with a sign: each car is sent down exactly one road, depending on the sign.
Why this matters: every business rule in a backend service ("orders above a limit need approval", "expired tokens are rejected") is a decision. This lesson builds directly on Module 10, where you learned the comparison operators (>=, ==) and logical operators (&&, ||, !) that produce the true or false answers an if needs. The next lesson extends one decision into a whole chain of them.
Learning Objectives
By the end of this lesson you will be able to:
- Explain that an
ifcondition must be abooleanexpression. - Write
if,if/else, and two-way decisions using braces. - Predict which lines run and which are skipped for a given input.
- Combine a comparison with
&&,||, or!inside a condition. - Explain why braces are always used, even for one statement.
- Recognize the
=versus==mistake and read the compiler message it causes.
Written Explanation
A condition is a question with a boolean answer
A condition is an expression whose value is true or false, the type boolean. Comparison expressions such as age >= 18 and n % 2 == 0 are conditions. So is a boolean variable on its own.
The if statement has this shape:
if (condition) {
// runs only when the condition is true
}When Java reaches the if, it evaluates the condition once. If the result is true, it runs the block in braces and then continues with the line after the block. If the result is false, it skips the block and continues. The Java Language Specification requires the condition to be of type boolean (or its wrapper Boolean); anything else is a compile-time error.
Adding an else
else is the other road: its block runs when the condition is false. Exactly one of the two blocks runs, never both and never neither.
if (age >= 18) {
System.out.println("Adult");
} else {
System.out.println("Minor");
}Without an else, the program simply does nothing extra when the condition is false. Both forms are normal. Use else when the false case needs its own action.
Building conditions
Most conditions are made from the operators you already know:
| Question in words | Condition |
|---|---|
| Is the number even? | n % 2 == 0 |
| Is the age at least 18? | age >= 18 |
| Is the quantity valid? | qty >= 1 && qty <= 100 |
| Is the account not blocked? | !blocked |
Two reminders from Module 10. First, chaining comparisons the way mathematics does (1 <= qty <= 100) does not work in Java; write two comparisons joined by &&. Second, && and || stop early when the answer is already known, so in x != 0 && 10 / x > 2 the division is never attempted when x is zero.
A boolean variable is a good way to name a tricky test:
boolean canWithdraw = amount > 0 && amount <= balance;
if (canWithdraw) {
// ...
}Always use braces
Java allows an if without braces, in which case only the next single statement belongs to it. This is a classic source of quiet bugs, because indentation means nothing to the compiler. Example 3 below shows it happening. The rule for this course: always write braces, even around one line. Then adding a second line later cannot silently escape the if.
One equals sign versus two
= stores a value; == compares two values. Writing if (x = 5) assigns 5 to x and then asks whether that assignment is a boolean. For int variables it is not, so the compiler stops you (see Common Mistakes). The risk is higher with boolean variables, where if (done = true) compiles and always assigns, so train yourself to read == as "is equal to".
Examples
Example 1: adult or minor (simple)
public class AgeCheck {
public static void main(String[] args) {
int age = 17;
if (age >= 18) {
System.out.println("Adult");
} else {
System.out.println("Minor");
}
System.out.println("Done");
}
}Output with age = 17:
Minor
DoneThe condition 17 >= 18 is false, so the if block is skipped and the else block runs. Done is printed in both cases because it sits after the whole if/else. Change age to 18 and rerun: the boundary value itself is an adult, because >= includes it.
Example 2: even or odd (practical)
Modulo (%) gives the remainder of a division, and an even number leaves remainder 0 when divided by 2.
int n = 7;
if (n % 2 == 0) {
System.out.println(n + " is even");
} else {
System.out.println(n + " is odd");
}Output:
7 is oddThis pattern ("test the remainder") appears constantly: every third row, every 100th record, alternating colours in a list.
Example 3: a withdrawal check and the missing-brace trap (realistic)
First the rule: a withdrawal must be positive and must not exceed the balance. Anything else is refused.
int balance = 150;
int amount = 200;
if (amount <= 0) {
System.out.println("Amount must be positive");
}
if (amount > balance) {
System.out.println("Not enough funds");
} else {
balance = balance - amount;
System.out.println("New balance: " + balance);
}
System.out.println("Done");Output:
Not enough funds
DoneTwo separate if statements are used here, so the first can reject a bad amount and the second can reject an amount that is too large. (Lesson 5 shows how to make a series of checks like this tidier.)
Now the trap. This program omits braces:
int stock = 0;
if (stock > 0)
System.out.println("In stock");
System.out.println("Ship it");
System.out.println("End");Real output:
Ship it
Endstock > 0 is false, so In stock is skipped, but Ship it was indented as if it belonged to the if and it does not. Only the first statement after the condition does. The program shipped an out-of-stock item. With braces around both lines, both would have been skipped.
Backend Insight
In a backend, an if is where a business rule becomes code. The inputs are usually fields of a request (an amount, a status, a role) and the output is "accept" or "reject". For example, a payment service might contain the rule "reject when the amount is zero or less, or above the daily limit". That is one condition with ||, and the whole rule is readable at a glance when you name the pieces.
Two habits matter more here than in small exercises. First, handle the rejecting cases explicitly: a missing else often means a silent failure, where a request is neither accepted nor reported as invalid. Second, write conditions in the language of the rule. amount > dailyLimit is easier to review than amount - dailyLimit > 0, and a reviewer comparing the code with the written requirement can spot a boundary error faster. In later modules, rejected requests turn into error responses; for now, printing a message is the same idea.
Common Mistakes
Mistake 1: Using = instead of ==
- Incorrect:
if (x = 5) { ... } - Correct:
if (x == 5) { ... }
For an int, the compiler catches it. Real message:
L01b.java:4: error: incompatible types: int cannot be converted to boolean
if (x = 5) {
^The message mentions boolean because the condition of an if must be one. Read it as "you gave me a number where I need a yes-or-no".
Mistake 2: Leaving out braces
- Incorrect: two indented lines under an
ifwithout braces; only the first one is controlled. - Correct: always braces, as in Example 3.
Mistake 3: Writing a semicolon right after the condition
- Incorrect:
if (n > 0); { ... } - Correct:
if (n > 0) { ... }
The stray ; is an empty statement, so the if controls nothing and the block after it always runs. If the output seems unaffected by your condition, look for this.
Mistake 4: Testing the opposite of what you meant
A condition such as age > 18 excludes 18 itself. When the rule says "18 or older", write >=. Test the exact boundary value by hand every time.
Exercises
Try each exercise yourself before opening the solutions. Where code is asked for, run it.
Level A: Foundation
A1. What type must the condition of an if have? Which of these are valid conditions for int n = 4;: n, n > 3, n = 3, n == 3?
Show solution A1
A1. The condition must be a boolean. n > 3 and n == 3 are valid. n is an int, so it is invalid. n = 3 is an assignment of an int, also invalid.
A2. Predict the output:
int temp = 30;
if (temp > 30) {
System.out.println("Hot");
} else {
System.out.println("Not hot");
}
System.out.println("End");Show solution A2
A2. temp > 30 is 30 > 30, false, so the else block runs:
Not hot
EndA3. Write an if/else that prints Pass when mark is at least 50, otherwise Fail.
Show solution A3
A3.
if (mark >= 50) {
System.out.println("Pass");
} else {
System.out.println("Fail");
}Level B: Application
B1. Write a condition that is true when an int year is a leap year candidate under this simplified rule: divisible by 4 and not divisible by 100. Test with 2024, 2100, and 2023.
Show solution B1
B1. year % 4 == 0 && year % 100 != 0. 2024: true. 2100: divisible by 4 but also by 100, so false. 2023: false. (The full rule has a third part about 400, which you can add later.)
B2. A cinema gives a discount to children under 12 and to seniors aged 65 or more. Using boolean eligible = ..., write the condition and print Discount or Full price. Test with ages 11, 12, 64, 65.
Show solution B2
B2.
boolean eligible = age < 12 || age >= 65;
if (eligible) {
System.out.println("Discount");
} else {
System.out.println("Full price");
}Ages 11 and 65 give Discount; 12 and 64 give Full price. Ages 12 and 11 are the boundary pair for the first part, 64 and 65 for the second.
B3. Predict the output, then explain why the second line prints:
int items = 0;
if (items > 0)
System.out.println("Packing");
System.out.println("Label printed");Show solution B3
B3. Output: Label printed. There are no braces, so only Packing belongs to the if. The condition is false, so Packing is skipped; the second println is not controlled by the if and always runs. Braces around both lines would skip both.
Level C: Challenge
C1. A password rule says: at least 8 characters, and (the user is an admin or the length is at least 12). Given int length and boolean admin, write one condition for it and test with these (length, admin) pairs: (7, true), (8, true), (8, false), (12, false).
Show solution C1
C1. length >= 8 && (admin || length >= 12). The parentheses are needed, because && binds tighter than ||. Results: (7, true) false; (8, true) true; (8, false) false; (12, false) true.
C2. Someone wrote if (stock = 0) for an int stock. Explain the compiler message you expect, and rewrite the line. Then explain why boolean done = false; if (done = true) would compile but be a bug.
Show solution C2
C2. For an int, stock = 0 is an assignment and has type int, so the compiler reports incompatible types: int cannot be converted to boolean. Rewrite as if (stock == 0). With a boolean variable the assignment done = true itself has type boolean, so it compiles; it sets done to true and the condition is always true, so the code runs when it should not.
Mini Challenge
Write a small program with hard-coded values for a parcel: weightKg (a double) and fragile (a boolean). Print Handle with care when the parcel is fragile. Separately, print Heavy: needs two people when the weight is above 20. Finally, print Standard handling only when it is neither fragile nor heavy.
Check your work: try all four combinations of fragile and heavy, including a weight of exactly 20 (which is not heavy). Write the four expected outputs before running the code.
Summary & Next Lesson
Key takeaways
- A condition is a
booleanexpression;if (condition) { ... }runs the block only when it is true, andelseruns when it is false. - Build conditions with comparison and logical operators; name complicated ones with a
booleanvariable. - Always use braces; indentation does not control the program.
=assigns,==compares. For anint, mixing them gives a compiler error aboutboolean.- Test the exact boundary value:
>and>=differ only there.
Next lesson
One if/else chooses between two roads. The next lesson, "else if chains and boundary values", handles three or more roads, such as mapping a score to a grade, and shows how to test the edges where the answer changes.
Self-check
- What happens if the condition of an
ifis false and there is noelse? - Write a condition for "the quantity is between 1 and 100 inclusive".
- What is wrong with
if (n > 0); { System.out.println("positive"); }? - Why should you write braces around a single-statement
ifbody? - For
age >= 18, which two ages are the most useful test inputs?
Show answers
- The block is skipped and execution continues with the next statement after the
if. qty >= 1 && qty <= 100.- The semicolon is an empty statement, so the
ifcontrols nothing; the block always runs. - Without braces only the next statement is controlled, and a line added later would look as if it belonged to the
ifwhile always running. - 17 and 18, the values just below and exactly at the boundary.
References
- Oracle, The Java Language Specification, Java SE 21, Chapter 14: Blocks, Statements, and Patterns. Supports the rules that an
ifcondition must be of typeboolean, and that anelsebelongs to the nearestif. - The compiler message and all program outputs in this lesson were produced by compiling and running the code with
javacandjavafrom JDK 21. The wording of compiler messages can differ slightly between JDK versions.
Practice
Apply this lesson with the module's lab, exercises and quiz.
Marking a lesson complete is optional and you can undo it any time. Your progress stays in this browser.