Java If, Else If, and Else
Choose which work runs, not just which boolean is true. Trace branches in order, separate independent checks from exclusive alternatives, and build a delivery quote that handles invalid input before selecting a tier.
Before you start: complete Java User Input with Scanner and review boolean expressions. The first examples use fixed values so you can focus on control flow; the lab uses prefilled editable input. All source examples run with the existing Java 21 runner.
What you will be able to do
- Trace which statements execute when an if condition is true or false.
- Choose between independent checks and one mutually exclusive branch chain.
- Order overlapping conditions and include the intended thresholds.
- Use braces, guard clauses, and scope deliberately.
- Assign a result on every continuing path before using it.
- Test an input-driven decision below, at, and above each boundary.
A boolean asks a question; if chooses what to execute
The operators lesson produced true or false. An if statement uses that answer to decide whether to execute a statement or block. Write the boolean condition in parentheses, then put the conditional work inside braces. In the first example, practiceMinutes >= 20 is false, so the target message is skipped.
After that skipped block, execution continues with Report complete. A false if condition does not automatically stop the program or skip every later statement. Change the minutes to 20 and trace the two output lines: the conditional message now runs, followed by the same final message.
Use a boolean expression, not a count by itself. Java does not treat a nonzero int as true. A condition such as seatsAvailable > 0 explains the intended meaning better than attempting if (seatsAvailable). Read each condition aloud as a question before deciding which work belongs inside its braces.
Main.java · An if can skip a block and continue
Predict the result, edit Main.java, then run your program.
Standard input · optional
Select Run code to compile and execute this program.
Report complete.
if and else choose between two alternatives
An else supplies the alternative when the if condition is false. For one execution of this if/else statement, only one of its two branches is selected. With zero seats, the no-seats message is selected; with a positive seat count, the available message is selected.
The final Checked capacity line is outside both branches, so it runs after either branch completes normally. Keep that shared work outside when it genuinely belongs to both paths. If a selected branch returns or throws, control does not simply fall through to that line; the guard-clause example will make that difference explicit.
else does not take a condition in parentheses. For another condition, write else if instead. Also distinguish an alternative message from a validation policy: this small example reports no seats for any nonpositive value, but does not establish that a negative stored capacity is acceptable input. The chosen domain still needs to be defined.
Main.java · Choose one of two paths
Predict the result, edit Main.java, then run your program.
Standard input · optional
Select Run code to compile and execute this program.
No seats available.
Checked capacity.
An else-if chain stops at its first true condition
Suppose a delivery rule offers free shipping at 5000 cents, a standard tier at 2500 cents, and a small-order tier below that. A subtotal of 5000 satisfies both >= 5000 and >= 2500. The order of the branch chain decides which matching rule gets selected.
Evaluate from top to bottom. At 5000, the first condition is true, its block runs, and the remaining else-if conditions and final else are not selected. At 3000, the first condition is false and the second true. At 1000, both conditions are false, so the final else runs. This is a first-match decision, not a process that runs every true block.
Put overlapping thresholds in an order that implements the policy. Here the highest threshold comes first. The second branch needs only >= 2500 because arriving there already means the first threshold was not met. These examples assume a valid nonnegative subtotal; the lab validates invalid and empty cases before choosing a shipping tier.
Main.java · Put the highest subtotal tier first
Predict the result, edit Main.java, then run your program.
Standard input · optional
Select Run code to compile and execute this program.
Free shipping tier.
Trace the boundary at 2500
- The 5000 comparison is false, so its block is skipped.
- The 2500 comparison is true, so Standard shipping tier is printed.
- The final else is not selected. The chain finishes after that one classification.
Now try 2499 and 5000. Explain which question is reached and which question is skipped.
Independent if statements answer independent questions
Two separate if statements are two separate decisions. A score of 85 meets both the foundation and advanced targets, so printing both achievements is reasonable. Joining them with else if would select only the first matching achievement and hide the other, which would be the wrong model for this report.
The else below belongs to the second if, not to the whole sequence of previous decisions. At a score of 60, the program prints Foundation target met and Advanced target not met. Those messages are compatible: one achievement was reached and another was not. Trace the braces rather than guessing from the visual proximity of a line.
Choose separate checks when multiple outcomes are allowed, such as independent warnings or achievements. Choose one chain when exactly one classification or price tier should win. If independent checks repeatedly assign the same result variable, a later assignment can overwrite an earlier one; that is the defect in the repair exercise.
Main.java · Separate if statements can both run
Predict the result, edit Main.java, then run your program.
Standard input · optional
Select Run code to compile and execute this program.
Foundation target met.
Advanced target met.
Braces define the controlled work; indentation only helps readers
Without braces, a plain if controls only its next statement. Indenting a second statement does not add it to the branch. Use braces consistently so adding a log message or calculation does not silently change which work is conditional. In nested code, braces also make the relationship between each if and else easier to see.
Do not put a semicolon immediately after the closing parenthesis of an if condition. In if (ready); the semicolon is an empty statement controlled by the if. A following braced block is then separate work and can execute even when ready is false. The program can compile while doing the opposite of what its indentation suggests.
An else associates with the nearest eligible unmatched if according to Java's syntax, not whichever earlier if looks closest to its indentation level. Prefer explicit braces instead of relying on that dangling-else rule. Match the opening and closing braces after each edit, then run both true and false paths.
A nested decision is reached only through its outer branch
The tools-preview example first asks whether the user is signed in. Only the true path then asks whether the user is a teacher. With signedIn true and teacher false, the inner else selects Student tools preview. If signedIn is false, neither inner tools branch is reached.
Nesting is useful when the second question only makes sense inside the first path. If several independent requirements simply need to be true together, a clear && expression may be shorter. Choose the structure that explains the decision rather than assuming deeper indentation means more complete validation.
These booleans are fixed teaching values. Printing a tools label does not authenticate a user, grant a role, or protect server resources. A real application needs trusted checks where an action is performed. For this example, change the two booleans through all combinations and explain which question is actually reached.
Main.java · A nested choice belongs to its outer path
Predict the result, edit Main.java, then run your program.
Standard input · optional
Select Run code to compile and execute this program.
Student tools preview.
A guard clause handles an early exit before the main work
A guard clause checks an unacceptable or special case near the top and exits that path. The name example handles a missing or blank value first. Its || short-circuit prevents isBlank from being called on null. Printing the required-name message explains the rejection; return then ends main.
Without that return, execution would continue and might call strip on null or print a misleading success message for blank input. Printing an error is not itself an exit. Always trace the statement after the guard block and ask whether the rejected path can still reach it.
After the guard returns for invalid inputs, the remaining code can be read as the accepted path. In these programs return exits main; inside another method it would exit that method, not magically stop every application thread. Use a small number of purposeful guards to reduce nesting without scattering unexplained exits throughout a large method.
Main.java · Stop an invalid path before using its value
Predict the result, edit Main.java, then run your program.
Standard input · optional
Select Run code to compile and execute this program.
A name is required.
Test missing, blank, and accepted names
null and three spaces both print only A name is required. The text Mina prints the welcome and ready lines. Removing return lets a rejected path continue: null then causes a method-call failure, while blank text can produce a misleading success message.
A result must be in scope and assigned on every path that uses it
A variable declared inside a branch block is local to that block. If a result is needed after the whole decision, declare it in the enclosing scope, then assign it in the appropriate branches. The status example declares one String variable before the if/else and assigns it on both continuing paths.
Java checks definite assignment before a local variable is read. Removing the else assignment can make the later print fail compilation, because the compiler cannot establish a value for every path. This matters even when you happen to expect a positive seat count at runtime. Do not silence the problem with a meaningless default merely to hide a missing case.
A path that returns before the later read does not need to assign the result for that read. That is how early guards and later complete classifications fit together. Explain each continuing path and the value it supplies. Shared calculations can then follow the branch rather than being copied into every block.
Main.java · Assign a result on both continuing paths
Predict the result, edit Main.java, then run your program.
Standard input · optional
Select Run code to compile and execute this program.
Status: Available
Write boundary expectations before running the code
For the shipping tiers, test 2499, 2500, 2501, 4999, 5000, and 5001 cents. These values exercise both exact thresholds and their immediate neighbours. Testing only a very small and a very large subtotal can miss a mistaken > where the rule requires >=.
Also test different paths, not just different numbers. The lab has missing input, text that cannot be parsed, a negative subtotal, an empty order, and each normal tier. A successful compilation does not prove that the branch order, fallback, or input policy is correct. Specify the expected output for each kind of path first.
Conditions are evaluated when execution reaches them. If you store a boolean and later change its input, that stored boolean does not update itself. Likewise, a selected if block is not a background rule that reruns whenever a variable changes. Make the timing of updates and decisions explicit when reading a trace.
Optional: use ?: for a small choice of one value
The conditional expression condition ? valueWhenTrue : valueWhenFalse selects one value. In the example, quantity == 1 chooses item; other quantities choose items. The selected value is assigned to unit, then used in one shared print statement. Only the selected alternative expression is evaluated.
This is an expression rather than an if statement: it produces a value with a type determined by Java's rules. Here both alternatives are Strings, keeping that type choice simple. It is not a replacement for arbitrary blocks of statements or a reason to hide multiple side effects inside one dense line.
Use an ordinary if/else for larger work, multiple statements, or a policy that benefits from named branches. Avoid nested conditional expressions while learning. The wording example also assumes an appropriate nonnegative quantity; choosing a plural word does not validate the number.
Main.java · Optional short choice of one value
Predict the result, edit Main.java, then run your program.
Standard input · optional
Select Run code to compile and execute this program.
1 item
Repair both the threshold and the overwritten result
Shipping should be 0 cents at a subtotal of 5000 or more, 300 cents from 2500 through 4999, and 500 cents below 2500. The starter prints 300 for 5000 and also overwrites a free result for larger subtotals. Repair both boundary comparisons and the relationship between the decisions.
Main.java · Repair the shipping tiers
Predict the result, edit Main.java, then run your program.
Standard input · optional
Select Run code to compile and execute this program.
Reveal the explained repair
The inclusive comparisons admit exactly 5000 and exactly 2500. One if/else-if/else chain prevents a later matching tier from overwriting an earlier selection. Declare the result once and assign it in every branch. These tiers assume a valid nonnegative subtotal; invalid and empty orders are handled separately in the lab.
Main.java · Repaired shipping tiers
Predict the result, edit Main.java, then run your program.
Standard input · optional
Select Run code to compile and execute this program.
Shipping (cents): 0
Independent lab: classify one delivery quote
Read one subtotal line and create a local delivery-quote preview. Handle missing, malformed, negative, and zero input before choosing exactly one shipping tier. This is an invented pricing exercise, not a real checkout, charge, or reservation.
- Use the first input line as one complete int subtotal in cents, with boundary whitespace stripped. Report missing input and parsing failure separately, then return.
- If the subtotal is negative, print Subtotal cannot be negative. and return. If it is zero, print No items to ship. and return.
- For a subtotal of 5000 or more, choose Free shipping and 0 cents shipping.
- Otherwise, for a subtotal of at least 2500, choose Standard shipping and 300 cents shipping; below that, choose Small-order shipping and 500 cents shipping.
- Assign shippingCents and deliveryLabel on every normal continuing branch. Then calculate totalCents and print the four labelled lines shown below.
- Test both sides of each threshold and every early-return case. Do not hard-code the expected calculated total.
The prefilled input is 2500 cents on one line. Expected output:
Subtotal (cents): 2500
Delivery: Standard shipping
Shipping (cents): 300
Total (cents): 2800
Main.java · Build your delivery quote
Predict the result, edit Main.java, then run your program.
Standard input · prefilled example
Select Run code to compile and execute this program.
Show hints without revealing the solution
Reuse the previous lesson's whole-line parsing pattern. Missing, malformed, negative, and zero subtotals each end their path before normal work. Declare the shared label and fee outside a descending-threshold chain, assign them in every branch, then calculate and print the total once.
Reveal the explained lab solution
Main.java · Delivery-quote solution
Predict the result, edit Main.java, then run your program.
Standard input · prefilled example
Select Run code to compile and execute this program.
The guards end rejected or empty paths before a quote is printed. At 2500, the free tier is false and the inclusive standard tier is true, giving 300 cents shipping and a 2800-cent total. Both result variables are assigned on every normal path. Only the first input line belongs to this contract; this is not a loop that quotes multiple orders.
Test changes and boundaries
Edit the input box for each test. Reset restores the original source and 2500-cent example.
- At 2499, expect Small-order shipping, 500 cents shipping, and a total of 2999. At 2500 and 2501, expect Standard shipping with 300 cents shipping.
- At 4999, shipping is still 300. At 5000 and 5001, Free shipping is selected and total equals subtotal.
- At -1, expect only the negative-subtotal message. At 0, expect only No items to ship. Neither path should print a quote.
- With no input, expect No subtotal supplied. A blank line or text such as three should instead produce the whole-int-value message.
- Enter 2147483648 to test a value beyond int range: it must be rejected as a parsing failure. Enter boundary whitespace around 2500 to confirm that the deliberate strip policy preserves the valid quote.
Common mistakes and how to diagnose them
A branch can compile and still implement the wrong policy. Trace the condition, the controlled block, and the next continuing statement before changing unrelated calculations.
A block runs even when the condition is false
Look for a stray semicolon after if (...) or a statement outside the intended braces. Indentation does not define a Java block. Run both truth values after repairing the structure.
The wrong price tier wins
Check overlapping conditions and their order. An else-if chain selects the first true condition. Separate if statements can select several branches and overwrite a result. Match the structure to the policy.
The exact threshold falls into the lower tier
Translate at least as >= rather than >. Test the boundary itself as well as its immediate neighbours. A few far-away passing values will not reveal the missing equality case.
An error message is followed by a success result
Printing an error does not stop execution. Use an appropriate return or alternative branch so rejected input cannot reach the normal result calculation.
cannot find symbol or variable might not have been initialized
A result may be declared only inside a branch, or a continuing path may never assign it. Declare shared results in the proper enclosing scope and cover every continuing case rather than adding arbitrary defaults.
An else belongs to the wrong if
Inspect the syntax and matching braces. An else pairs with its nearest eligible unmatched if, not the indentation you intended. Explicit blocks and a smaller decision structure make the relationship visible.
Frequently asked questions
Can if be used without else?
Yes. A false condition then skips the controlled block and continues after the if. An else is useful when a meaningful alternative belongs to the same decision.
Does every true else-if condition run?
No. The chain selects the first matching branch and skips the remaining alternatives. Use independent if statements when several outcomes are meant to occur.
Does return always stop the entire application?
It exits the current method. In these small examples it exits main, ending the normal workflow. Larger programs may have callers or other threads, so do not generalize it into a universal application shutdown command.
Can I use = inside a condition?
Assignment and comparison are different. Assigning an int does not produce the boolean required here. A boolean assignment can compile while accidentally changing state, so prefer a clear flag or comparison and keep updates separate.
When should I use ?: instead of if/else?
Use it for a small readable choice of a value, such as a singular/plural label. Prefer ordinary blocks for multiple statements, complex branching, or decisions that need clearer intermediate names.
Trace one path, then test the paths you did not select
An if chooses work from a boolean result. An else-if chain selects its first match, while independent if statements can each run. Braces define scope and controlled work; return exits the current method. Shared results need a value on every path that reaches their use.
Before moving on, explain why the lab validates before choosing a tier, why 5000 must come before 2500, and why a zero order never reaches the small-order quote. Next is Java Switch.
Can you explain which branch actually runs?
Answer all six questions and read the reasoning. Results are temporary on this page and do not save course progress.
References and related learning
The decision scenarios, examples, explanations, and exercises are original SovranCode material. These official references support the language rules.
- Java 21 specification: if statements
- Java 21 specification: blocks and statement structure
- Java 21 specification: definite assignment
- Java 21 specification: conditional expressions
Review input validation · Review conditions and boundaries · Java course roadmap.
Last updated: