if / else if / else

The if statement is Java's fundamental decision-making tool, letting a program execute different code paths based on boolean conditions.

Almost every non-trivial program needs to make decisions, and if/else if/else is the most basic mechanism Java provides for that. An if statement evaluates a boolean condition and executes one block of code if it's true, optionally chaining further conditions with else if, and providing a final catch-all with else.

Boolean Conditions

The condition in an if statement must be an expression of type boolean (or Boolean, via auto-unboxing) — unlike some other languages, Java does not allow arbitrary numeric or reference values to be treated as truthy/falsy. An int condition, for example, will not compile.

int x = 5;
// if (x) { ... }         // COMPILE ERROR: int cannot be used as a boolean condition
if (x != 0) { ... }        // correct: an explicit boolean expression

Simple if

The simplest form executes its block only when the condition evaluates to true; otherwise the block is skipped entirely and execution continues after it.

int age = 20;
if (age >= 18) {
    System.out.println("Adult");
}

if-else

Adding an else clause provides an alternative block that runs exactly when the condition is false — exactly one of the two blocks executes.

int age = 15;
if (age >= 18) {
    System.out.println("Adult");
} else {
    System.out.println("Minor");
}

else-if Chains

Chaining else if lets you test a series of conditions in order; Java evaluates them top to bottom and executes the block belonging to the first condition that's true, skipping all the rest — including any subsequent conditions that might also be true. A trailing else (optional) catches the case where none of the conditions matched.

An else-if chain is really just nested if/else statements, formatted flat by convention: else { if (...) { ... } } is written else if (...) { ... }. Understanding this equivalence explains why exactly one branch executes.

int score = 85;
if (score >= 90) {
    System.out.println("A");
} else if (score >= 80) {
    System.out.println("B");
} else if (score >= 70) {
    System.out.println("C");
} else {
    System.out.println("F");
}
// prints "B" — the first matching branch wins, later ones are never even checked

Nested Conditions

if statements can be nested inside other if or else blocks to express conditions that depend on other conditions already being true.

Deep nesting hurts readability; combining conditions with && or restructuring with early returns/guard clauses is usually preferable once nesting exceeds two or three levels.

int age = 25;
boolean hasLicense = true;
if (age >= 18) {
    if (hasLicense) {
        System.out.println("Can drive");
    } else {
        System.out.println("Needs a license");
    }
} else {
    System.out.println("Too young to drive");
}

Braces

Braces {} are technically optional when a branch has exactly one statement — Java allows a single unbraced statement as the body of an if, else, or else-if. This is legal but widely discouraged in professional code, because it is a common source of bugs when someone later adds a second statement, assuming it's still 'inside' the branch.

if (age >= 18)
    System.out.println("Adult");     // legal without braces — but risky style

if (age >= 18)
    System.out.println("Adult");
    System.out.println("Can vote"); // MISLEADING: this line always runs, regardless of the if!

The Dangling-Else Rule

When an if without braces is immediately followed by another if and then a single else, Java resolves the ambiguity by binding the else to the nearest unmatched if — not the outer one, regardless of indentation, which can mislead a reader relying on visual formatting alone.

Always using braces, even for single-statement bodies, eliminates the dangling-else ambiguity entirely and is the standard recommended style precisely for this reason.

if (a > 0)
    if (b > 0)
        System.out.println("both positive");
    else
        System.out.println("a positive, b not"); // this else binds to 'if (b > 0)', NOT 'if (a > 0)'
// Indentation here is misleading if a <= 0: neither branch executes at all,

if as an Alternative to switch/ternary

if/else if is the most general conditional construct — it can express arbitrary boolean logic, unlike switch (which tests one value against several discrete cases) or the ternary operator (which is an expression, not a statement, and best suited to short value selections). Choosing between them is a matter of what best expresses the logic: many discrete values against one variable often reads better as switch; a single value-selecting expression often reads better as a ternary.

// Many discrete cases on one variable: switch may read better
// A boolean-logic-heavy decision: if/else fits naturally
if (temperature > 30 && humidity > 70) {
    System.out.println("Uncomfortably hot and humid");
}

Practical Complete Example

public class GradeReport {
    public static void main(String[] args) {
        int score = 78;
        boolean lateSubmission = true;

        String grade;
        if (score >= 90) {
            grade = "A";
        } else if (score >= 80) {
            grade = "B";
        } else if (score >= 70) {
            grade = "C";
        } else if (score >= 60) {
            grade = "D";
        } else {
            grade = "F";
        }

        if (lateSubmission) {
            System.out.println("Grade: " + grade + " (late penalty may apply)");
        } else {
            System.out.println("Grade: " + grade);
        }
    }
}

Quick Reference

if (condition) { ... }
if (condition) { ... } else { ... }
if (c1) { ... } else if (c2) { ... } else { ... }
Condition must be boolean — no implicit numeric/reference truthiness
Only the FIRST matching branch in an else-if chain executes
Braces optional for single statements, but strongly recommended always
Dangling else binds to the nearest unmatched if

Key Takeaways

An if condition must be a genuine boolean expression — Java has no implicit truthiness for numbers or references.

In an else-if chain, exactly the first true condition's branch executes; all subsequent conditions are skipped even if also true.

Braces are optional for single-statement bodies but should be used consistently to avoid dangling-else ambiguity and accidental scope bugs.

The dangling-else rule binds an else to the nearest unmatched preceding if, which can silently defy indentation-based expectations.

Deeply nested if statements usually indicate an opportunity to simplify with combined conditions, early returns, or a switch statement.

if (x) doA(); doB(); // mistakenly assumed to be part of the if if (x) { doA(); doB(); }

Without braces, only the single statement immediately following if belongs to it. doB() here always executes regardless of x, which is rarely the intended behavior.

if (isReady = true) {... } // assignment instead of comparison if (isReady == true) {... } // or simply: if (isReady)

= is assignment; it compiles here only because isReady is boolean, but it silently reassigns isReady to true and always takes the branch, rather than checking its current value.

if (score >= 60) grade = "D"; if (score >= 70) grade = "C"; if (score >= 80) grade = "B"; if (score >= 90) grade = "A"; // separate ifs, not else-if if (score >= 90) grade = "A"; else if (score >= 80) grade = "B"; else if (score >= 70) grade = "C"; else if (score >= 60) grade = "D";

Using separate if statements instead of else-if means all matching conditions execute in sequence, so a score of 95 ends up assigned "D" and overwritten repeatedly, landing on the LAST matching branch instead of the intended highest one — else-if with descending thresholds ensures only the first (correct) match wins.

Why does if (x) fail to compile when x is an int in Java, unlike some other languages?

Java requires the condition of an if statement to be an actual boolean (or Boolean) expression — it has no implicit conversion of numeric or reference values to true/false, so a non-boolean condition is a compile-time type error.

In a chain of if/else if/else if/else, how many branches execute if two of the conditions are both true?

Exactly one — the block belonging to the first condition (evaluated top to bottom) that is true. Once a branch is taken, all remaining else-if/else clauses in that chain are skipped, even if their conditions would also be true.

What is the dangling-else problem, and how does Java resolve it?

It arises when an if without braces is immediately followed by another if and then a single else, creating ambiguity about which if the else belongs to. Java resolves it by binding the else to the nearest unmatched preceding if, regardless of how the code is indented.

Why is omitting braces around a single-statement if body considered risky, even though it's legal?

Without braces, only the one statement immediately following the if is actually part of the conditional body. If a developer later adds a second statement intending it to be conditional too, it silently executes unconditionally instead — a bug that's easy to introduce and hard to spot visually.

What is the difference in behavior between using a chain of else-if statements versus a sequence of independent if statements to assign a grade based on score thresholds?

In an else-if chain, only the first matching condition's branch runs. With independent if statements, every condition that evaluates to true executes its branch in sequence, potentially overwriting an earlier correct assignment with a later, less appropriate one.

Can the condition of an if statement have side effects, such as an assignment or a method call with observable effects? Give an example.

Yes — any boolean-typed expression is legal, including ones with side effects, such as if ((result = compute()) > 0) { ... }, which assigns to result as part of evaluating the condition. This is legal but should be used sparingly since it can hurt readability.

Why might deeply nested if statements be considered a design smell, and what are two common ways to address it?

Deep nesting makes code harder to read and reason about, since the reader must track many simultaneously active conditions. Common remedies include combining conditions with logical operators (&&, ||) into fewer, flatter checks, and using early returns/guard clauses to exit a method as soon as a disqualifying condition is detected.

Write a method classify(int n) that returns "negative", "zero", or "positive" based on the sign of n, using if/else if/else.

static String classify(int n) { if (n < 0) { return "negative"; } else if (n == 0) { return "zero"; } else { return "positive"; } }

Exactly one branch executes based on which condition matches first: negative numbers take the first branch, zero takes the second (since it fails the first check), and everything else falls to the else branch.

What does this print, and how does the dangling-else rule affect the structure here?

It prints "non-positive". The inner else ("small positive") binds to the nearest unmatched if (a > 100) by the dangling-else rule, forming a self-contained inner if/else; the outer if (a > 0) has its own separate else, which is the one that actually executes since a is -1.

Write code using nested if statements (with braces) that prints an eligibility message: a person can enter a contest if they are at least 13 years old AND, if they are under 18, they also have parental consent.

int age = 15; boolean hasConsent = true; if (age >= 13) { if (age < 18) { if (hasConsent) { System.out.println("Eligible with consent"); } else { System.out.println("Needs parental consent"); } } else { System.out.println("Eligible (adult)"); } } else { System.out.println("Too young"); }

The nested structure checks the base age requirement first, then branches further only for minors to require consent, and always uses braces so the nesting structure is unambiguous regardless of indentation.

int a = -1;
if (a > 0)
    if (a > 100)
        System.out.println("big");
    else
        System.out.println("small positive");
else
    System.out.println("non-positive");