Intro to Conditionals (with Tracing)
if, if/else, and the mystery-trace skill that catches bugs before you run
Every program you have written so far runs top to bottom, one statement after another. That works fine for a unit converter that always does the same five operations on any input. It does not work for a chat bot that has to say different things depending on what the user types. For that you need the if statement — Java’s tool for making decisions.
In a nutshell
An if statement runs a block of code only when a boolean expression is true. The optional else clause runs when the expression is false. Exactly one of the two branches runs. Never both. Never neither.
Reading conditionals by hand (tracing them) is a different skill from writing them, and it comes first. You will trace small “if/else mystery” problems for the rest of CS1 — the skill is that important. Tracing builds the mental model that lets you write correct conditionals and debug wrong ones.
When you are done with this lesson you will be able to write an if or an if/else with proper Java syntax, trace a short conditional program by hand and predict its output, and describe what a method signature (return type, name, parameters) means.
Quick reference
Syntax
// single branch — runs only when expression is true
if (boolean-expression) {
...
}
// two branches — runs exactly one of them
if (boolean-expression) {
...
} else {
...
}
Rules you will see Java enforce over and over:
- The expression inside
(...)must beboolean. Java rejectsif (5)— no “truthy” integers like in C or Python. - Always use braces, even for a single statement. Skipping them is legal but causes silent bugs.
- Never put a
;right after the(...).if (x > 0);ends theifas an empty statement; the block that follows runs always.
Comparison operators (recap from lesson 2-d)
| Operator | Meaning |
|---|---|
== |
equal to |
!= |
not equal to |
< / > |
less than / greater than |
<= / >= |
less than or equal / greater than or equal |
Do not chain these like algebra. 0 < x < 100 is not valid Java. Java’s type checker rejects it: 0 < x produces a boolean, and you cannot then compare a boolean to the integer 100. You will see a compile error along the lines of “bad operand types for binary operator <.” Use && to combine the two comparisons: 0 < x && x < 100.
Tracing algorithm
- Substitute the given input values into the variables at the top.
- Walk through the statements one by one.
- For each conditional, evaluate the boolean expression and follow the true or false branch.
- Write the current values of every variable after each statement that changes one.
- Write each line the program prints, in order.
Deep dive
1. The if statement
int score = 85;
if (score >= 60) {
System.out.println("Passing");
}
The condition score >= 60 is a boolean expression — it evaluates to true or false. When true, Java runs the block in braces. When false, Java skips the block and moves on. No magic.
Three syntax rules the compiler will remind you of, repeatedly, until they become reflex.
The condition must be boolean. C and Python let you write if (5) because non-zero values are “truthy.” Java does not. An int inside if (...) is a compile error — the compiler wants an expression that is exactly true or false.
int count = 5;
if (count) { ... } // compile error
if (count > 0) { ... } // correct — explicit boolean comparison
Always use braces, even for one statement. This compiles:
if (score >= 60)
System.out.println("Passing");
It even works. But the moment you add a second line intending it to be inside the if:
if (score >= 60)
System.out.println("Passing");
System.out.println("Well done"); // ALWAYS prints
the compiler reads only the first println as controlled by the if. The second one runs every time, no matter what score is. The indentation is for you, not for the compiler. Braces remove the ambiguity:
if (score >= 60) {
System.out.println("Passing");
System.out.println("Well done");
}
No semicolon after the condition. This is a silent bug, not a compile error:
if (score >= 60);
{
System.out.println("Passing");
}
The ; ends the if as an empty statement. The {...} that follows is a standalone block that runs unconditionally. Result: Passing prints regardless of score, and you will spend 20 minutes wondering why.
2. if/else picks exactly one path
Add else to provide the alternate branch:
if (score >= 60) {
System.out.println("Passing");
} else {
System.out.println("Not passing");
}
Exactly one branch runs. If the condition is true, the if block runs and the else is skipped. If false, the if is skipped and the else runs. Not both. Not neither.
Compare that to what happens with two separate if statements:
// if/else — one branch fires
if (score >= 60) {
System.out.println("Passing");
} else {
System.out.println("Not passing");
}
// separate ifs — BOTH can fire
if (score >= 60) {
System.out.println("Passing");
}
if (score < 60) {
System.out.println("Not passing");
}
The second version happens to work because the two conditions are exact negations of each other — exactly one will be true. But if a future edit gets one condition slightly wrong, both branches can fire or neither can fire. The if/else form encodes the structure of the decision directly: there are two cases, they cover everything, exactly one applies. That structure is worth leaning on whenever it fits.
3. Tracing — the skill that catches bugs before you run them
Reading code is as important as writing it. Given a small conditional program, you should be able to predict the output before you press run. Here is the canonical trace:
public static void mystery(int a, int b) {
int c = 0;
if (a < b) {
c = a + 2;
} else {
c = b - 1;
}
System.out.println(c);
}
The line public static void mystery(int a, int b) is a method signature — don’t worry about it in depth yet; you’ll write your own starting Week 5. For now, read it as “mystery is a little function that takes two int inputs named a and b and runs the code below it. A call like mystery(3, 10) makes a equal 3 and b equal 10, then runs the body.”
Trace mystery(3, 10):
c = 0,a = 3,b = 10.a < b?3 < 10is true. Run theifblock:c = 3 + 2 = 5.- Print
5.
Trace mystery(5, 5):
c = 0,a = 5,b = 5.a < b?5 < 5is false. Strict less-than — equality doesn’t count. Run theelse:c = 5 - 1 = 4.- Print
4.
The second trace is the instructive one. The boundary case (a == b) falls into the else branch. Students who remember < as “less than or equal” will predict the wrong output. Always substitute the actual numbers and check. Trust the operator, not your feelings.
c when a = 7 and b = 7?
int c = 0;
if (a < b) {
c = a + 2;
} else {
c = b - 1;
}a < b is 7 < 7, which is false — strict less-than, so equality doesn't count. The else branch runs: c = b - 1 = 6. This is the classic boundary-case trap — if you remembered < as "less than or equal," you picked A.
A first look at methods and return types
You will write your own methods in Week 5, but you have already been calling a lot of them — Math.sqrt, .length(), .equalsIgnoreCase(...). The vocabulary is worth seeing now.
A method signature looks like this:
public static double sqrt(double x)
Read left to right:
public static— modifiers (covered later; for now they mean “you can call this from anywhere”).double— the return type. This method produces adouble.sqrt— the method name.(double x)— the parameter list. This method takes onedoubleargument, which the method callsx.
When you call Math.sqrt(25), four things happen:
- Java evaluates the argument
25and binds it to the parameterx. - Java runs the method body.
- The method produces a return value — here,
5.0. - Java hands the value back to you, where you use it in an expression.
A method with return type void does not produce a value. System.out.println is void — it prints something, but there is no value to capture. That is why double x = System.out.println("hi"); is a compile error.
This is exactly the pattern you have been using every time you called a String or Math method. You already know the shape; now you also know the names.
Before you leave
if and if/else are the most-used control structures in all of programming. Every program that responds differently to different inputs uses some version of them. The next lesson takes them further — nested conditionals, the dangling else, and the three-way patterns that show up in Lab 5.