Decision structures: if/else, logical operators, switch
if, else if chains, nested if, short-circuiting with &&, || and !, switch and fall-through. On the midterm it comes both as output tracing and as writing getSeason-style methods.
Until now the program ran every line from top to bottom. Decision structures (selection statements) let you run some lines and skip others depending on a condition. Two kinds of questions come up on the midterm: following the conditions to find what is printed, and writing short methods that say “return this for that value” (letter grade, month name, season).
Golden rules:
- In an else if chain the first true branch runs, and the rest are not looked at.
- Without curly braces an if covers a single statement. Indentation misleads.
&&and||short-circuit: once the result is known, the right side does not run at all.- In a switch, without break it falls through (fall-through), default included.
=is assignment,==is comparison.=inside an if does not compile.
Comparison and boolean expressions
Relational operators compare two values and produce a boolean (true/false).
| Operator | Meaning | when a = 7, b = 3 |
|---|---|---|
== | equal? | a == b → false |
!= | not equal? | a != b → true |
> < | greater, less | a > b → true |
>= <= | greater or equal, less or equal | a <= 7 → true |
int a = 7, b = 3;
System.out.println((a > b) + " " + (a == b) + " " + (a != b) + " " + (a <= 7));
boolean big = a > 5;
System.out.println(big);
true false true true
true
A boolean can be stored in a variable and printed directly.
PITFALL · a single equals sign inside an if.
if (x = 5)does not compile:incompatible types: int cannot be converted to boolean. An if wants a boolean, andx = 5is an assignment that produces an int.
if and if-else
int temp = 12;
if (temp > 25) {
System.out.println("Sicak");
} else {
System.out.println("Serin");
}
System.out.println("Bitti");
Serin
Bitti
If the condition is true, the if block runs; if it is false, the else block runs. Exactly one of the two runs. The lines after the block (Bitti) run in every case.
The else if chain
When there are several ranges, you use else if. Java tries the conditions from top to bottom, runs the first true one, and skips the rest of the chain.
public static String letter(int score) {
if (score >= 90) return "A";
else if (score >= 80) return "B";
else if (score >= 70) return "C";
else if (score >= 60) return "D";
else return "F";
}
Calls letter(85), letter(90), letter(59):
B A F
When we reach the score >= 80 branch for 85, we already know score < 90; so there is no need to write score >= 80 && score < 90.
PITFALL · wrong order. If you start the chain from the small end, like
if (score >= 60) return "D"; else if (score >= 70) ..., even a student with 95 gets a D, because the first true condition is>= 60. During verificationletterWrongOrder(95)really returnedD. When you work with lower bounds, order them from largest to smallest.
A chain and separate ifs are different:
int s = 95;
if (s >= 90) System.out.print("A ");
if (s >= 80) System.out.print("B ");
if (s >= 70) System.out.print("C ");
A B C
Three separate ifs, all three are checked independently and all three are true.
Curly brace and semicolon traps
int x = -2, cnt = 0, other = 0;
if (x > 0)
cnt++;
other++; // the indentation misleads: this line is OUTSIDE the if
System.out.println(cnt + " " + other);
int y = -5;
if (y > 0); // the ; at the end is an empty statement, it is the if's body
{
System.out.println("pozitif?");
}
0 1
pozitif?
In the second example the body of the if is that empty semicolon. The curly brace block below has nothing to do with the if and always runs. pozitif? was printed even though y is negative.
Dangling else
int m = 5, n = 20;
if (m > 10)
if (n > 10)
System.out.println("ikisi de buyuk");
else
System.out.println("else kime ait?");
System.out.println("son");
son
An else always belongs to the nearest unmatched if: here the inner if (n > 10). The indentation makes it look as if it belonged to the outer if, but Java does not look at indentation. Because the outer condition is false, nothing inside ran. The way to avoid this: always use { }.
Logical operators
| a | b | a && b (AND) | a || b (OR) | !a (NOT) |
|---|---|---|---|---|
| true | true | true | true | false |
| true | false | false | true | false |
| false | true | false | true | true |
| false | false | false | false | true |
Precedence: first !, then &&, last ||. Comparisons are done before these, which is why age >= 18 && student works without parentheses.
int age = 20;
boolean student = true;
System.out.println(age >= 18 && student);
System.out.println(age < 18 || !student);
System.out.println(!(age == 20));
System.out.println(true || false && false); // && first: true || false
System.out.println((true || false) && false);
true
false
false
true
false
Short-circuit evaluation
&&: if the left side is false, the result is already false, and the right side is not looked at.||: if the left side is true, the result is already true, and the right side is not looked at.
This is used as a guard:
int d = 0;
if (d != 0 && 10 / d > 1) System.out.println("buyuk");
else System.out.println("guvenli");
guvenli
Because d != 0 is false, 10 / d was never computed and the program did not crash. If you had written the order the other way round (10 / d > 1 && d != 0) you would get an ArithmeticException.
If the right side has a side effect like ++z, short-circuiting means that side effect never happens. The midterm sets exactly this trap.
The conditional operator (ternary)
condition ? value1 : value2 is a short if-else; it produces a value.
int t1 = 8;
String parity = (t1 % 2 == 0) ? "even" : "odd";
System.out.println(parity);
even
switch
You use switch to branch on specific values of a variable. It works with int, char, String (and byte, short); it cannot be written with double or boolean.
int day = 3;
switch (day) {
case 1: System.out.println("Mon"); break;
case 2: System.out.println("Tue"); break;
case 3: System.out.println("Wed"); break;
default: System.out.println("Other");
}
Wed
The rule: Java jumps to the matching case, starts running downward from there, and continues until it sees a break. If no case matches, default runs (like else). default is not required.
Fall-through
int lvl = 2;
switch (lvl) {
case 1: System.out.println("one");
case 2: System.out.println("two");
case 3: System.out.println("three");
default: System.out.println("default");
}
two
three
default
It entered at case 2, and because there was no break, everything below ran, default included. case 1 stayed above, so it did not run: a switch never goes above the matching case.
Fall-through is also used on purpose: if several values do the same job, you write the cases one under another.
char g = 'B';
switch (g) {
case 'A': case 'B': System.out.println("Iyi"); break;
case 'C': System.out.println("Orta"); break;
default: System.out.println("Zayif");
}
String cmd = "stop";
switch (cmd) {
case "go": System.out.println("Gidiyor"); break;
case "stop": System.out.println("Duruyor"); break;
default: System.out.println("?");
}
Iyi
Duruyor
switch inside a method: with return
If the method returns a value, you write return in every case. Because return ends the method immediately, no break is needed. daysInMonth in the question bank above is an example of this pattern; the season, day name and letter grade questions are solved with the same skeleton.
Common mistakes
| Wrong idea | The truth |
|---|---|
if (x = 5) | if (x == 5); a single = does not compile |
| In else if, all true branches run | Only the first true branch |
| Indentation decides the scope of an if | Without { } it is only one statement |
if (x > 0); is harmless | Empty body; the block below always runs |
| else belongs to the outer if | To the nearest unmatched if |
a || b && c goes left to right | && first: a || (b && c) |
The ++z on the right of a condition always runs | With short-circuiting it never runs |
| switch runs the matching case and leaves | Without break it falls through |
switch works with double | It does not; use int, char, String |
Compare a String with == | equals; switch does this itself for Strings |
Test yourself
Exam-style questions. Solve them on paper first, then reveal the answer.
What is printed?
int x = 15;
if (x > 10) System.out.println("A");
else if (x > 5) System.out.println("B");
else System.out.println("C");Show answer
In an else if chain, the first true branch runs and the rest are not looked at. 15 > 10 is true → A. 15 > 5 is also true, but that branch is never reached.
What is printed?
int x = 15;
if (x > 10) System.out.print("A");
if (x > 5) System.out.print("B");
else System.out.print("C");
System.out.println();Show answer
This time there are two separate ifs. The first if prints A. The second if is checked independently: 15 > 5 is true → B. The else belongs only to the second if, so it does not run.
What is printed?
int a = 4, b = 9;
System.out.println(a > 3 && b < 5);
System.out.println(a > 3 || b < 5);
System.out.println(!(a > 3) || b % 3 == 0);Show answer
true
true
1) true && false → false. 2) true || false → true. 3) !(true) = false; 9 % 3 == 0 is true; false || true → true.
What is printed?
int x = 0;
if (x > 0)
System.out.println("pos");
System.out.println("checked");Show answer
Without curly braces, the if covers only the single statement right below it. Indentation means nothing to Java. The checked line is outside the if and always runs.
What is printed when day is (a) 2, (b) 4, (c) 7?
switch (day) {
case 1: System.out.println("Red");
case 2: System.out.println("Green");
case 3: System.out.println("Blue"); break;
case 4: System.out.println("Black");
default: System.out.println("White");
}Show answer
(a) Enter at case 2, there is no break → fall through to case 3 (fall-through), Blue, break → exit. (b) Enter at case 4, no break → falls into default: Black, White. (c) No case matches → only default: White. Each word is printed on its own line.
What is printed?
int q = 3, z = 0;
if (q > 5 && ++z > 0) System.out.println("in");
System.out.println(z);
if (q < 5 || ++z > 0) System.out.println("in2");
System.out.println(z);Show answer
in2
0
Short-circuit: if the left of && is false, it never looks at the right, so ++z does not run → z = 0. If the left of || is true, it does not look at the right, so again ++z does not run → z is still 0. Because the condition is true, in2 is printed.
What is printed?
int a = 2, b = 8;
if (a > 5)
if (b > 5)
System.out.println("X");
else
System.out.println("Y");
System.out.println("Z");Show answer
Dangling else: the else belongs to the nearest unmatched if, regardless of indentation, that is if (b > 5). Because the outer if (a > 5) is false, everything inside is skipped. Only Z is printed.
What is printed?
int n = 7;
String res = (n > 5) ? (n > 10 ? "big" : "medium") : "small";
System.out.println(res);Show answer
The conditional operator (ternary) is condition ? a : b. 7 > 5 is true → look at the inner expression: 7 > 10 is false → "medium".
What is printed?
String w = "B";
switch (w) {
case "A": System.out.print("1 ");
case "B": System.out.print("2 ");
case "C": System.out.print("3 "); break;
default: System.out.print("4 ");
}Show answer
switch works with String too (it compares with equals). "B" matches → 2 , no break → 3 , break. default is never reached.
What is printed?
int score = 72;
if (score >= 90) System.out.println("A");
if (score >= 70) System.out.println("C");
else if (score >= 60) System.out.println("D");
else System.out.println("F");Show answer
The first if is independent and false. The second if starts a separate chain: 72 >= 70 is true → C, and the rest of the chain is skipped.
Write a static method daysInMonth(int month) that uses a switch to return 28 for February, 30 for April, June, September and November, 31 for the other months, and -1 for an invalid month.
Show answer
Write the cases that give the same result one under another (deliberate fall-through). Because return ends the method, no break is needed.public static int daysInMonth(int month) { switch (month) { case 2: return 28; case 4: case 6: case 9: case 11: return 30; case 1: case 3: case 5: case 7: case 8: case 10: case 12: return 31; default: return -1; }}Test: daysInMonth(4) → 30, daysInMonth(7) → 31, daysInMonth(2) → 28, daysInMonth(13) → -1.
Write a static method isLeapYear(int year): a year is a leap year if it is divisible by 4 but not by 100, or if it is divisible by 400. Use a single return statement.
Show answer
Translate the rule word for word into logical operators. Although && has higher precedence than ||, writing parentheses improves readability.public static boolean isLeapYear(int year) { return (year % 4 == 0 && year % 100 != 0) || year % 400 == 0;}Test: 2024 → true, 1900 → false (divisible by 100, not by 400), 2000 → true, 2026 → false.
Verification: All outputs were run with JDK 26 (verify/SEN1001/W03.java). The daysInMonth and isLeapYear methods were tested with several inputs. The if (x = 5) error was obtained by compiling verify/SEN1001/err/IfAssign.java with javac.