The Java if-else statement runs one block of code when a boolean condition is true and another block when it is false. The else part is optional, and chaining else if lets us pick one branch out of several.
We use if-else for every decision that depends on data at runtime, such as validating input, choosing a price tier, or handling a missing value before we call a method on it.
The following example charges a shipping fee only for orders under 50.
double total = 42.0;
double fee;
if (total >= 50) {
fee = 0.0;
} else {
fee = 4.99;
}
double payable = total + fee; // 46.99
Notice that only one of the two blocks runs, never both and never neither. We start with the condition rules, move on to else if chains and nesting, and finish with pattern matching, guard clauses and the alternatives to if-else.
1. if Statement Syntax and the Condition
An if statement has a condition in parentheses and a statement after it. The statement runs only when the condition evaluates to true. When we leave out else, nothing happens for false and the program continues with the next line.
double total = 30.0;
double fee = 0.0;
if (total < 50) {
fee = 4.99; // runs, 30 is under 50
}
double payable = total + fee; // 34.99
The condition must have the type boolean or Boolean. Unlike C and JavaScript, Java does not treat numbers, null or empty strings as false, so a C-style check does not compile.
// does not compile: incompatible types, int cannot be converted to boolean
int items = 3;
if (items) {
System.out.println("cart has items");
}
The same rule catches the classic typo if (items = 0), because an assignment of an int is not a boolean. A Boolean object is allowed, but Java unboxes it, so a null value throws NullPointerException. For an optional flag, compare with Boolean.TRUE instead.
Boolean giftWrap = null; // customer did not choose
boolean wrap = Boolean.TRUE.equals(giftWrap); // false, no exception
boolean unsafe = giftWrap; // NullPointerException
2. Choosing Between Several Branches with else if
An else if chain, often called an if-else-if ladder, tests the conditions from top to bottom. The first condition that is true wins, its block runs, and Java skips every remaining condition. The final else runs only when none of the conditions matched.

The following example is a discount rule from an online shop. Orders of 100 or more get 15 percent off, orders of 50 or more get 5 percent, and smaller orders pay the full price.
static int discountPercent(double total) {
if (total >= 100) {
return 15;
} else if (total >= 50) {
return 5;
} else {
return 0;
}
}
int big = discountPercent(120); // 15
int medium = discountPercent(60); // 5
int small = discountPercent(20); // 0
Because the first match wins, the most specific condition must come first. If we swap the two checks, an order of 120 also matches total >= 50, so the 15 percent branch can never run.
static int discountWrongOrder(double total) {
if (total >= 50) {
return 5;
} else if (total >= 100) {
return 15; // never reached
} else {
return 0;
}
}
int wrong = discountWrongOrder(120); // 5, the 15 branch is dead code
Java has no elif or elseif keyword. The else if form is an else whose statement is another if, so a chain can be as long as we need, although a long chain that compares one variable against constants reads better as a switch statement.
3. Nested if Statements and the Dangling else
A nested if is an if inside the block of another if. We nest when the second question only makes sense after the first one is answered. For example, a shop checks the express delivery cutoff only for members who pay for express delivery.
static String deliverySlot(boolean member, int hour) {
if (member) {
if (hour < 14) {
return "today";
} else {
return "tomorrow";
}
} else {
return "in 3 days";
}
}
String early = deliverySlot(true, 10); // "today"
String late = deliverySlot(true, 16); // "tomorrow"
String guest = deliverySlot(false, 10); // "in 3 days"
Braces are optional when a branch has a single statement, but leaving them out causes two well-known bugs. The first one is the dangling else. Without braces, an else belongs to the nearest if, whatever the indentation suggests.
static String slotNoBraces(boolean member, int hour) {
String slot = "in 3 days";
if (member)
if (hour < 14)
slot = "today";
else // belongs to if (hour < 14)
slot = "tomorrow";
return slot;
}
String guestSlot = slotNoBraces(false, 10); // "in 3 days", the else never ran
The indentation says that guests get the else branch, but Java attaches the else to the inner if. The second bug happens when we add a line to a braceless branch. Only the first line belongs to the if, so the compiler rejects the else that follows.
// does not compile: 'else' without 'if'
int stock = 5;
int reserved = 0;
if (stock > 0)
stock = stock - 1;
reserved = reserved + 1;
else
System.out.println("sold out");
Putting braces around every branch avoids both bugs, and most style guides and formatters enforce it.
4. Combining Conditions with &&, || and !
A condition can join several checks with the logical operators && (and), || (or) and ! (not). The && and || operators are short-circuit operators, which stop evaluating as soon as the result is known.
We use that rule to guard a method call against null. In the following coupon check, code.isBlank() runs only when code is not null, so the check never throws an exception.
static boolean isValidCoupon(String code) {
if (code != null && !code.isBlank() && code.startsWith("SAVE")) {
return true;
}
return false;
}
boolean ok = isValidCoupon("SAVE10"); // true
boolean blank = isValidCoupon(" "); // false
boolean none = isValidCoupon(null); // false, no NullPointerException
When a condition grows past two or three checks, we move it into a well-named method such as isValidCoupon() or a local boolean variable. The boolean article covers the operators and the Boolean wrapper in more depth.
5. Type Checks with instanceof Patterns
Since Java 16, the condition of an if can test a type and declare a variable in one step with pattern matching for instanceof (JEP 394). The variable exists only where the test is known to be true, so we need no cast.
static String describeDiscount(Object discount) {
if (discount instanceof Integer percent && percent > 0) {
return percent + "% off";
} else if (discount instanceof String code) {
return "coupon " + code;
} else {
return "no discount";
}
}
String percentText = describeDiscount(10); // "10% off"
String couponText = describeDiscount("SAVE5"); // "coupon SAVE5"
String zeroText = describeDiscount(0); // "no discount"
The pattern variable also works with a negated test. When the if block always leaves the method, the variable is in scope after the if, which is known as flow scoping.
static int couponLength(Object input) {
if (!(input instanceof String code)) {
return 0;
}
return code.length(); // code is in scope here
}
int len = couponLength("SAVE10"); // 6
int noLen = couponLength(42); // 0
6. Guard Clauses Instead of Deep Nesting
A guard clause is an if at the top of a method that handles one invalid case and returns or throws right away. Each guard removes one level of nesting, so the main logic stays at the left margin and reads from top to bottom.
Say a checkout service validates an order before it charges the customer. The nested version keeps the success path three levels deep, and every else sits far away from the if it belongs to.
static String checkoutNested(List<String> cart, String address, boolean paid) {
if (!cart.isEmpty()) {
if (address != null) {
if (paid) {
return "shipped";
} else {
return "awaiting payment";
}
} else {
return "missing address";
}
} else {
return "empty cart";
}
}
The version with guard clauses returns the same results. Each rule is one short if next to its outcome, so we add a new rule without touching the others.
static String checkout(List<String> cart, String address, boolean paid) {
if (cart.isEmpty()) {
return "empty cart";
}
if (address == null) {
return "missing address";
}
if (!paid) {
return "awaiting payment";
}
return "shipped";
}
String shipped = checkout(List.of("book"), "Pune", true); // "shipped"
String empty = checkout(List.of(), "Pune", true); // "empty cart"
String unpaid = checkout(List.of("book"), "Pune", false); // "awaiting payment"
String same = checkoutNested(List.of("book"), null, true); // "missing address"
7. if-else Statement vs Ternary Operator vs switch
Java offers two other ways to branch, and each fits a different shape of decision. The ternary operator condition ? a : b is an expression, so it fits when both branches only produce a value for one variable.
double total = 75.0;
String shipping = total >= 50 ? "free" : "standard"; // "free"
int age = 18;
boolean isAdult = age >= 18; // true, no ternary needed
A condition already is a boolean, so age >= 18 ? true : false adds nothing over age >= 18. Nested ternaries are hard to read, and we replace them with if-else or a switch expression.
| Construct | Best fit | Watch out for |
|---|---|---|
| if-else | Ranges, combined conditions, different actions per branch | Deep nesting and long chains |
| Ternary ? : | Picking one of two values in one expression | Nesting, side effects in the branches |
| switch | One variable compared against many constants, enums or types | Fall-through in the old colon form |
Speed is not a reason to pick one form over another. The JIT compiler optimizes all three, and the readable version is the right one.
8. if-else Statement FAQs
Developers who start with if-else in Java ask these questions most often.
8.1. Can we use if without else in Java?
Yes. The else part is optional. Without it, nothing runs when the condition is false, and the program continues after the if block.
8.2. Are curly braces required for a single statement?
No, the compiler accepts a single statement without braces. We still add them, because braceless code leads to the dangling else and to lines that look like part of a branch but are not, as section 3 shows.
8.3. How many else if blocks can one if statement have?
The language sets no limit. Past four or five branches, a switch, a Map lookup or polymorphism often keeps the code easier to change.
8.4. Is switch faster than if-else in Java?
Not in a way that matters for application code. The compiler can turn a dense switch into a jump table, but the JIT also optimizes if-else chains, so we choose by readability.
9. Conclusion
The if-else statement runs one of two blocks based on a boolean condition, and else if chains extend it to several branches where the first true condition wins. Put the most specific condition first, and use braces on every branch to avoid the dangling else.
Short-circuit operators guard against null, instanceof patterns remove casts, and guard clauses keep methods flat. For a single value, the ternary operator is shorter, and for many constants of one variable, a switch reads better.
10. References
- JLS 25, The if Statement
- JLS 25, Statements (dangling else)
- JLS 25, Conditional Operator ? :
- JEP 394, Pattern Matching for instanceof
- Oracle Java Tutorials, The if Statements
Happy Learning !!