Java If Else
The if statement runs a block of code only when a condition is true. Adding else provides an alternative path, and chaining else if handles several mutually exclusive cases. Together they are the most direct way to make a program choose what to do.
The if Statement
if (condition) {
// runs only when condition is true
}
int temperature = 38;
if (temperature > 35) {
System.out.println("Heat warning: stay hydrated.");
}
System.out.println("Forecast complete.");
Output:
Heat warning: stay hydrated.
Forecast complete.
The condition in parentheses is evaluated once. If it is true, the block runs; if false, the block is skipped entirely and execution continues after the closing brace. The last line runs in both cases because it is outside the block.
The parentheses are mandatory, and the condition must be a boolean expression. if (temperature) does not compile.
The else Clause
else supplies a block that runs when the condition is false. Exactly one of the two blocks runs.
int marks = 42;
if (marks >= 50) {
System.out.println("Pass");
} else {
System.out.println("Fail");
}
Output:
Fail
else has no condition of its own. It is the "otherwise" case for the if immediately before it.
else if Chains
When there are more than two outcomes, chain conditions with else if:
int score = 76;
char 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';
}
System.out.println("Grade: " + grade); // Grade: C
How the chain is evaluated
Conditions are tested top to bottom, and the first one that is true wins. Its block runs and every remaining branch is skipped, even if later conditions would also be true.
For score = 76:
76 >= 90: false, move on.76 >= 80: false, move on.76 >= 70: true. Assign'C'and leave the chain.
The fourth condition, 76 >= 60, is never evaluated, though it is also true. This is why the chain can use only lower bounds: reaching the >= 70 test already implies the score is below 80.
Order matters
Reordering the same conditions breaks the logic:
if (score >= 60) {
grade = 'D'; // every passing score lands here
} else if (score >= 70) {
grade = 'C'; // unreachable for any score
} ...
With range checks, order from the most restrictive to the least restrictive (here, highest threshold first).
The final else
The trailing else catches everything not matched above. Without it, a chain might run no branch at all. In the grade example, the final else also guarantees that grade is assigned on every path; remove it and the compiler reports that grade might not have been initialized when it is printed.
Separate ifs Versus else if
Several independent if statements are not the same as an else if chain:
int n = 15;
// Independent checks: every true condition runs
if (n % 3 == 0) System.out.println("divisible by 3");
if (n % 5 == 0) System.out.println("divisible by 5");
// Chain: only the first true condition runs
if (n % 3 == 0) {
System.out.println("divisible by 3");
} else if (n % 5 == 0) {
System.out.println("divisible by 5");
}
The first form prints both lines; the second prints only divisible by 3. Use separate ifs when the conditions are independent and several may apply. Use a chain when the cases are mutually exclusive and exactly one should apply.
Braces and Single Statements
When a branch contains one statement, braces are optional:
if (balance < 0)
System.out.println("Overdrawn");
else
System.out.println("OK");
Omitting them invites a specific bug when code is added later:
if (balance < 0)
System.out.println("Overdrawn");
sendAlert(); // NOT part of the if: runs every time
Indentation means nothing to the compiler; only the first statement belongs to the if. Always using braces makes the structure explicit and prevents this.
A stray semicolon causes the same kind of problem:
if (balance < 0); {
System.out.println("Overdrawn"); // always runs
}
The ; is an empty statement that serves as the entire body of the if. The block below is an independent statement.
Nested if Statements
An if can appear inside another if or else block:
boolean loggedIn = true;
boolean isAdmin = false;
if (loggedIn) {
if (isAdmin) {
System.out.println("Admin dashboard");
} else {
System.out.println("User dashboard");
}
} else {
System.out.println("Please log in");
}
The dangling else
Without braces, an else always belongs to the nearest preceding unmatched if:
if (loggedIn)
if (isAdmin)
System.out.println("Admin");
else
System.out.println("Please log in"); // actually pairs with if (isAdmin)
Despite the indentation, a logged-in non-admin sees "Please log in", and a logged-out user sees nothing. Braces remove the ambiguity.
Flattening with early returns
Deep nesting is hard to follow. Inside a method, checking failure cases first and returning early keeps the main logic at one level:
// Nested
void withdraw(Account acc, double amount) {
if (acc != null) {
if (!acc.isFrozen()) {
if (amount <= acc.getBalance()) {
acc.debit(amount);
} else {
System.out.println("Insufficient funds");
}
} else {
System.out.println("Account frozen");
}
}
}
// Guard clauses
void withdraw(Account acc, double amount) {
if (acc == null) return;
if (acc.isFrozen()) {
System.out.println("Account frozen");
return;
}
if (amount > acc.getBalance()) {
System.out.println("Insufficient funds");
return;
}
acc.debit(amount);
}
Both behave identically. In the second, each rejection is handled next to the check that triggers it, and the successful path is the last unindented line.
Combining Conditions Instead of Nesting
Two nested ifs with no else on the outer one can be merged with &&:
if (age >= 18) {
if (hasId) {
allowEntry();
}
}
// equivalent
if (age >= 18 && hasId) {
allowEntry();
}
Keep the nesting only when the outer branch has its own else or does additional work.
if Versus the Ternary Operator
When an if/else exists only to assign one of two values to a variable, the ternary operator expresses it in one line:
String status;
if (stock > 0) {
status = "In stock";
} else {
status = "Sold out";
}
String status = stock > 0 ? "In stock" : "Sold out";
Use if when the branches execute statements (printing, calling methods, updating several variables) or when there are more than two outcomes.
Variables Declared Inside Branches
A variable declared in a branch exists only inside that block:
if (isMember) {
double discount = 0.1;
}
System.out.println(discount); // compile error: discount not in scope
To use a value after the if, declare the variable before it and assign it in each branch:
double discount;
if (isMember) {
discount = 0.1;
} else {
discount = 0.0;
}
System.out.println(discount);
The compiler checks that every path assigns discount; omitting the else would be a compile error.
Practical Example: Electricity Bill with Slab Rates
Utility bills are often charged in slabs: each band of units has its own rate.
public class ElectricityBill {
static double calculate(int units) {
if (units < 0) {
throw new IllegalArgumentException("Units cannot be negative");
}
double amount;
if (units <= 100) {
amount = 0; // first 100 units free
} else if (units <= 200) {
amount = (units - 100) * 2.25;
} else if (units <= 500) {
amount = 100 * 2.25 + (units - 200) * 4.50;
} else {
amount = 100 * 2.25 + 300 * 4.50 + (units - 500) * 6.60;
}
if (amount > 0) {
amount += 50; // fixed charge, only when billed
}
return amount;
}
public static void main(String[] args) {
int[] readings = {80, 150, 350, 620};
for (int u : readings) {
System.out.printf("%4d units -> %8.2f%n", u, calculate(u));
}
}
}
Output:
80 units -> 0.00
150 units -> 162.50
350 units -> 950.00
620 units -> 2417.00
The first if rejects invalid input before any calculation. The chain then picks exactly one slab, from lowest to highest; because earlier branches have already handled smaller values, each test needs only an upper bound. Each branch adds the full cost of the lower slabs plus the partial cost of the current one. For 350 units: 100 × 2.25 = 225, plus 150 × 4.50 = 675, giving 900, plus the fixed charge of 50. A second, independent if applies the fixed charge, since it is a separate rule rather than another case of the slab choice.