Java Nested if Statement

In the last lesson you learned about the Java if-else statement. But some decisions come in layers, where you ask the next question only if the first one is true. For decisions that stack like this, Java lets you put an if inside another if, called a nested if.

πŸ€” Why do we need nesting?

Some questions only make sense after an earlier one passes. Picture a login screen:

  • First, does this username exist?

  • Only if it does, is the password correct?

  • You would never check the password first. A missing user has no password to compare.

  • So the password check lives inside the username check. It runs only when the outer check is true.

  • That is a nested if: do the outer check first, and only then step inside for the next one.

🧩 What a nested if looks like

A nested if is just an if written inside the block of another if:

if (outerCondition) {
// βœ… runs when the outer condition is true
if (innerCondition) {
// βœ… runs only when BOTH are true
}
}

Read it from the outside in:

  • Java checks outerCondition first. If it is false, the whole block is skipped and the inner if is never seen.
  • If it is true, Java steps inside and checks innerCondition.
  • So the inner code runs only when both are true. The order matters, and that is what sets nesting apart from two side-by-side checks.

Now with real values: check a number for positive first, then for even.

int number = 8;
if (number > 0) {
System.out.println("It is positive");
if (number % 2 == 0) {
System.out.println("And it is even");
}
}
  • number > 0: 8 is greater than 0, so we step inside and print the first line.
  • number % 2 == 0: 8 divides evenly, so it is true too and prints the second line.
  • Change number to -8 and the outer check fails. The whole block is skipped and the inner if is never reached.

Output

It is positive
And it is even

πŸ”’ The inner check only runs when the outer is true

The inner if is locked behind the outer one, like a door inside a room. You can only try the inner door after walking through the outer one. Here we check a user’s role:

String role = "guest";
if (role.equals("admin")) {
System.out.println("Welcome admin");
if (role.equals("admin")) {
System.out.println("You can delete records");
}
}
System.out.println("Done");
  • role.equals("admin") compares the role to β€œadmin”. Our role is β€œguest”, so it is false.
  • Java skips the whole outer block. The inner check never runs and nothing inside prints.
  • The program jumps to the line after the block.

Output

Done

If the outer condition is false, the inner one never gets a turn. That shielding is useful: the inner check can safely assume the outer thing is already true.

✏️ Indentation and readability

Indentation shows what lives inside what. Each level deeper shifts the code further right:

if (loggedIn) { // level 1
if (hasPermission) { // level 2, inside level 1
if (fileExists) { // level 3, inside level 2
System.out.println("Opening file");
}
}
}
  • Every if sits one step further right than the one holding it, so your eye follows the staircase.
  • The matching closing brace } lines up under its own if.
  • When braces and indentation agree, you see at a glance which block ends where. When they do not, bugs hide easily.

Let your editor indent for you

Most editors will auto-indent and even match braces for you. Use that. If your indentation looks messy after a paste, run your editor’s format command. Clean spacing is the cheapest way to spot a missing brace.

πŸ”— Flatten with && instead of deep nesting

Not every nested if needs to be nested. When the inner if just adds another condition, join the two with && and drop a layer. Here is the nested version, which acts only when both checks pass:

int age = 25;
boolean hasLicense = true;
if (age >= 18) {
if (hasLicense) {
System.out.println("Allowed to drive");
}
}

The inner if is purely a second gate. We can fold both into one condition with &&, which means both sides must be true:

int age = 25;
boolean hasLicense = true;
if (age >= 18 && hasLicense) { // βœ… same logic, one level
System.out.println("Allowed to drive");
}

Both versions print the same thing, but the flattened one is shorter.

Output

Allowed to drive

When does each read better?

  • Use && when both checks guard the same action with nothing special in between.
  • Keep them nested when the outer block does extra work first (like printing a message), or when the inner if has its own else.

πŸ—οΈ Avoiding the pyramid of doom

Nest too deeply and the code drifts right until it looks like a sideways pyramid. People call this the pyramid of doom. It is hard to read and easy to break. Here is a withdrawal check as a deep pyramid, with the real work buried inside:

boolean cardValid = true;
boolean pinCorrect = true;
double balance = 500;
double amount = 200;
if (cardValid) {
if (pinCorrect) {
if (amount <= balance) {
System.out.println("Withdrawal approved");
}
}
}

The meaningful line is buried three levels in. Flip it around with guard clauses.

  • A guard clause checks the bad case first and leaves early.
  • That keeps the happy path flat at the bottom.
  • Inside a method, leaving early means using return.
public static void withdraw(boolean cardValid, boolean pinCorrect,
double balance, double amount) {
if (!cardValid) { // βœ… check the bad case, leave early
System.out.println("Card is not valid");
return;
}
if (!pinCorrect) {
System.out.println("PIN is wrong");
return;
}
if (amount > balance) {
System.out.println("Not enough balance");
return;
}
System.out.println("Withdrawal approved"); // happy path, no nesting
}

With all good values, no bad case fires, so it falls through to the bottom.

Output

Withdrawal approved
  • Each problem is handled and dismissed right away with return.
  • The ! means β€œnot”, so !cardValid is true when the card is not valid.
  • By the last line you already know every check passed.
  • The code reads top to bottom like a checklist instead of marching deeper. That is the main trick for readable conditional code.

🎯 Worked example: eligibility check

Here the outer block does its own work before the inner check, so nesting reads well. We greet the applicant first, then decide eligibility:

int age = 20;
boolean isCitizen = true;
if (age >= 18) {
System.out.println("Age requirement met");
if (isCitizen) {
System.out.println("You are eligible to vote");
} else {
System.out.println("Only citizens can vote");
}
} else {
System.out.println("You must be at least 18");
}
  • age >= 18: 20 passes, so it prints the age message and steps inside.
  • isCitizen is true, so it prints the eligible message. The inner else is skipped.

Output

Age requirement met
You are eligible to vote

Nesting is the right call here: the outer block has its own message and else, and the inner check has a different else. A single && could not express all that cleanly.

πŸŽ“ Worked example: grade with bonus

Here a second decision sits inside the first. We work out a grade, and only for top scores check for a bonus mark:

int score = 92;
boolean perfectAttendance = true;
if (score >= 90) {
System.out.println("Grade: A");
if (perfectAttendance) {
System.out.println("Bonus: gold star for attendance");
}
} else {
System.out.println("Grade: B or lower");
}
  • 92 passes score >= 90, so it prints β€œGrade: A” and steps inside.
  • The attendance flag is true, so it adds the bonus line.
  • A lower score lands in the outer else and never reaches the bonus check.

Output

Grade: A
Bonus: gold star for attendance

The bonus only matters for A students, and nesting expresses that: the bonus question is asked only after the grade says A.

⚠️ Common Mistakes

Nested ifs bring a few traps that catch almost everyone early on.

Over-nesting when && would do. A second condition with no extra work is a layer for nothing.

// ❌ Avoid: extra nesting for two simple conditions
if (isMember) {
if (amount >= 100) {
System.out.println("Discount applied");
}
}
// βœ… Good: one flat condition with &&
if (isMember && amount >= 100) {
System.out.println("Discount applied");
}

Mismatched braces. Each { needs its }. In nested code it is easy to miss one, and then the wrong code ends up in the wrong block.

// ❌ Avoid: the inner if is never closed, code will not compile
if (loggedIn) {
if (isAdmin) {
System.out.println("Admin panel");
}
// βœ… Good: every opening brace has a matching closing brace
if (loggedIn) {
if (isAdmin) {
System.out.println("Admin panel");
}
}

The dangling else. Without braces, an else attaches to the nearest if, not the one you meant. A classic bug.

// ❌ Avoid: no braces, so else pairs with the INNER if, not the outer
if (age >= 18)
if (hasTicket)
System.out.println("Enter");
else
System.out.println("Too young"); // actually runs when age>=18 but no ticket
// βœ… Good: braces make it clear which if the else belongs to
if (age >= 18) {
if (hasTicket) {
System.out.println("Enter");
}
} else {
System.out.println("Too young");
}

βœ… Best Practices

Habits that keep nested decisions clean and safe:

  • Flatten with && when you can. If the inner if is only a second gate, join the conditions instead of nesting.
  • Use guard clauses for bad cases. Check failures first and leave early with return, keeping the success path flat.
  • Keep nesting shallow. Two levels is fine. Three is a warning sign. Beyond that, refactor with && or guard clauses.
  • Always use braces. They stop the dangling else bug and make block boundaries obvious, even for one-line bodies.
  • Indent each level clearly. Let your editor format the code so the staircase lines up and missing braces stand out.

🧩 What You’ve Learned

Nicely done. Let’s recap.

  • βœ… A nested if is an if placed inside another if, for decisions that depend on a prior decision.
  • βœ… The inner condition runs only when the outer is true, so the inner check is shielded by the outer one.
  • βœ… Indentation and matching braces show which block lives inside which.
  • βœ… When the inner if is just a second condition, flatten it with && for cleaner code.
  • βœ… Keep nesting for cases where the outer block does its own work or has its own else.
  • βœ… Avoid the pyramid of doom with guard clauses that handle bad cases early and keep the happy path flat.

Check Your Knowledge

Test what you learned. Pick an answer for each question, then click Check.

  1. 1

    In a nested if, when is the inner condition checked?

    Why: The inner if sits inside the outer block, so it is only checked after the outer condition is true.

  2. 2

    Two simple conditions both guard the same action with no extra work. What reads best?

    Why: When the inner if is just a second gate, flattening with && is shorter and clearer than nesting.

  3. 3

    What is the pyramid of doom?

    Why: Too many nested levels push the real work deep to the right, making code hard to read and maintain.

  4. 4

    How do guard clauses keep code flat?

    Why: Guard clauses handle each bad case early with return, so the success path stays flat at the bottom.

πŸš€ What’s Next?

You can stack decisions in layers now. But many decisions are not layered, they are a list of choices, like grades A, B, C, D, and F. For that you line up conditions one after another with else if. Let’s learn the ladder next.

Java else-if Ladder

Share & Connect