Lesson 4 of 915 min2 challenges

if / switch, and Why == Lies About Strings

The difference between == and equals — the most-asked Java interview question, for good reason.

Making decisions

int score = 85;

if (score >= 90) {
    System.out.println("Excellent");
} else if (score >= 60) {
    System.out.println("Pass");
} else {
    System.out.println("Fail");
}

Prints Pass. The first test, 85 >= 90, is false. The second, 85 >= 60, is true, so that branch runs and the whole chain is done — the else never gets looked at.

That last part matters. An if/else-if chain is not a list of independent questions. It's a sequence that stops at the first yes. Which is why order matters: if you'd checked >= 60 first, a score of 95 would print Pass, because it would match before the stricter test ever ran. Always put the narrowest condition first.

Compared to Python there are only three differences: the condition goes inside round brackets, the body goes inside curly braces, and elif is spelled else if.

Don't skip the braces

Java lets you leave the braces off when the body is a single statement:

if (score >= 60)
    System.out.println("Pass");

Don't. Here's what happens the day you add a second line:

if (score >= 60)
    System.out.println("Pass");
    System.out.println("Congratulations");   // runs no matter what

Without braces, the if owns exactly one statement — the first one. The second println is just the next statement in the method. It runs whether the score is 95 or 12.

Your eyes read the indentation and conclude both lines belong to the if. The compiler doesn't read indentation at all. This exact mistake shipped in Apple's TLS code in 2014 and broke certificate validation for millions of devices; it's known as "goto fail." Real consequences, from a missing pair of braces.

Habit to build now: every if, every else, every loop gets braces. No exceptions, not even for one line.

Logical operators

&&    // and — both sides must be true
||    // or — either side is enough
!     // not — flips it

if (age >= 18 && hasTicket) { ... }
if (age < 6 || age >= 65) { ... }

Java uses symbols where Python uses the words and, or, not. If you're coming from Python, you will type and at least once and get a syntax error. That's normal.

&& and || have a property called short-circuit evaluation: in a && b, if a is already false, b is never evaluated at all. There's no point — the answer can't change.

That's not a micro-optimization, it's a safety tool:

if (name != null && name.length() > 0) { ... }

If name is null, the first test fails and Java stops. name.length() never runs. Flip the order and you get a NullPointerException in exactly the case you were trying to guard against. Short-circuiting is what makes null checks work.

Comparing strings: == is the wrong tool

This is the most-asked question in Java interviews, and it isn't trivia — it's a real bug that ships.

String a = "hello";
String b = new String("hello");

System.out.println(a == b);        // false
System.out.println(a.equals(b));   // true

a == b prints false even though both hold the word "hello."

Here's the model to hold in your head. A String variable doesn't contain the text. It contains a pointer to where the text lives. == compares the two pointers: "are these the same object?" equals() walks the characters and compares them: "do these say the same thing?"

a and b above are two separate objects that happen to contain identical characters. Same text, different addresses. == says false, and it's telling the truth — it just isn't answering the question you meant to ask.

Rule: always compare strings with .equals().

There's a safer spelling worth adopting:

if ("admin".equals(role)) { ... }

Put the literal first. If role is null, "admin".equals(null) calmly returns false. Written the other way round, role.equals("admin") throws a NullPointerException. This trick is called a Yoda condition (because it reads backwards), and it eliminates a whole category of crash for free.

switch: many branches, one value

When you're comparing one variable against a list of fixed values, a long else-if chain gets noisy. switch is clearer:

int day = 3;
switch (day) {
    case 1:
    case 2:
    case 3:
    case 4:
    case 5:
        System.out.println("Weekday");
        break;
    case 6:
    case 7:
        System.out.println("Weekend");
        break;
    default:
        System.out.println("Not a valid day");
}

Prints Weekday.

Never forget break. Without it, execution doesn't stop at the end of a case — it keeps running straight into the next one. This is called fall-through, and it is on by default.

The code above uses fall-through deliberately: cases 1 through 4 have no body at all, so they fall into case 5's body. That's the idiomatic way to make several values share one action. But deliberate fall-through and forgotten-break fall-through look identical on the page, which is why the accidental kind is such a classic bug.

Java 14 added a form with no break at all:

String type = switch (day) {
    case 1, 2, 3, 4, 5 -> "Weekday";
    case 6, 7 -> "Weekend";
    default -> "Invalid";
};
System.out.println(type);

Prints Weekday. The arrow form never falls through, and it produces a value you can assign.

Check your version with java -version before reaching for it. On Java 11 or older this is a syntax error, and plenty of environments — including some classroom setups and this site's code runner — are still on 11. Prefer the arrow form where you can, and stay fluent in the old form, because it's in every codebase written before 2020.

The ternary operator

int score = 85;
String result = (score >= 60) ? "Pass" : "Fail";
System.out.println(result);

Prints Pass. Read it as: if the condition holds, take the value after ?; otherwise take the value after :.

It's good for a short either/or. Don't nest them — nested ternaries are unreadable, and a plain if/else costs you nothing.

Ten-second check

Can "abc" == "abc" be true in Java?

Yes, sometimes — Java keeps a pool of string literals and reuses the same object for identical ones written in source code, so both sides may genuinely be the same object. But never rely on it. The moment one side is built at runtime — read from Scanner, joined with +, loaded from a file — you get a different object and == turns false. Use .equals() every time and the question stops mattering.

Ad slot (AdSense not configured; ads appear here in production)

Hands-on

Reading it isn't knowing it. Writing it is.

0/2 passed

Challenges and grading are completely free, and a wrong answer costs you nothing. Stuck? Hit "Ask the AI": it can see the code you are writing.

Level 01Multiple choice+10 pts · +15 XP

How do you compare strings?

You want to know whether two strings hold the same **text**. Which line does that?

  • Might be multiple choice. Wrong answers cost nothing, so just try.
Level 02Write code+15 pts · +25 XP

Grade a score

Read one whole number from input and print its grade: 90 and up prints `Excellent`, 80 to 89 prints `Good`, 60 to 79 prints `Pass`, anything lower prints `Fail`.

Sample input

95

Expected output

Excellent
javaTab = 4 spaces

Finished? Mark it

Marking it done saves your progress, gives you 20 XP and keeps your streak alive.