skip to content

Explain short-circuit evaluation with && and ||, and give a practical reason it matters.

level: juniorimportance: must knowfreq 80%

answer

  1. false && X → false (skip X); true || X → true (skip X)
  2. Left evaluated first, always left-to-right
  3. Null-guard pattern: obj != null && obj.method()
  4. Skipped operand's side effects never run
  5. Order operands: cheap/guarding check first

basics

~20 s

With && and ||, Java checks the left side first and skips the right side if the answer is already known. false && X stays false without running X; true || X stays true without running X. This lets you safely null-check before using a value.

solid answer

~50 s

Short-circuit evaluation means && and || evaluate their left operand first and only evaluate the right operand when the outcome is still undecided. For &&, a false left operand makes the whole expression false, so the right operand is skipped. For ||, a true left operand makes it true, so the right is skipped. The practical payoff is twofold: performance (skip expensive work) and, more importantly, safety — you can guard a potentially failing call. The classic pattern is `if (obj != null && obj.isValid())`: if obj is null, the right side never runs, avoiding a NullPointerException. The order of operands therefore becomes meaningful: put the cheaper or guarding check first. A subtle consequence is that side effects in the skipped operand (assignments, method calls, increments) simply do not happen, which can surprise people who rely on them.

code

java · 16 lines
java
String name = null;

// SAFE: short-circuit skips length() when name is null
if (name != null && name.length() > 0) {
    System.out.println("non-empty");
}

// WOULD THROW NPE if reordered:
// if (name.length() > 0 && name != null) { ... }

int[] counter = {0};
java.util.function.BooleanSupplier f = () -> { counter[0]++; return true; };

boolean a = false && f.getAsBoolean();  // f skipped; counter stays 0
boolean b = true  || f.getAsBoolean();  // f skipped; counter stays 0
System.out.println(counter[0]);          // prints 0

go deeper

for a junior

Can explain false&&X / true||X skip the right side and use the obj != null && obj.method() guard.

for a middle

Understands side effects in the skipped operand don't run and orders operands deliberately for safety and speed.

for a senior

Reasons about operand ordering for performance hot paths and explains why relying on skipped side effects is a code smell; contrasts with & / |.

for a principal

Codifies null-guard and operand-ordering conventions, spots short-circuit-dependent side effects in review, and considers readability vs. micro-optimization trade-offs across a codebase.

## The core idea **Short-circuit evaluation** (also called *lazy* or *minimal* evaluation) means Java stops evaluating a logical expression as soon as the final result is certain. It applies to the two short-circuiting operators `&&` and `||`. Think about how the truth tables behave: - For **`A && B`** (AND): if `A` is `false`, the result is `false` no matter what `B` is. So Java doesn't bother computing `B`. - For **`A || B`** (OR): if `A` is `true`, the result is `true` no matter what `B` is. So Java doesn't bother computing `B`. Java **always evaluates the left operand first**, then decides whether the right operand is needed. ## Why this matters #1 — null-safety guards The most important everyday use is guarding against errors. A **NullPointerException (NPE)** happens when you call a method on a `null` reference. Consider: ```java if (user != null && user.isActive()) { ... } ``` If `user` is `null`, the left operand `user != null` is `false`, so `&&` short-circuits and `user.isActive()` is never called — no NPE. If you wrote them in the wrong order, `user.isActive() && user != null`, you'd crash on a null `user`. **Operand order is part of the logic.** The OR mirror image: ```java if (input == null || input.isBlank()) { return; } ``` If `input` is `null`, the left is `true`, so `||` short-circuits and `input.isBlank()` is skipped — again no NPE. ## Why this matters #2 — performance / avoiding work Put cheap, likely-decisive checks first so expensive ones are skipped: ```java if (cache.contains(key) || database.lookup(key)) { ... } ``` If the in-memory `cache.contains(key)` is `true`, the costly `database.lookup(key)` is never executed. ## Why this matters #3 — side effects can be skipped A **side effect** is anything an expression does besides producing a value — printing, mutating a variable, incrementing a counter, calling a method that changes state. With short-circuiting, side effects in the skipped operand **do not run**: ```java int calls = 0; boolean f() { calls++; return true; } boolean r = false && f(); // f() is skipped; calls stays 0 boolean s = true || f(); // f() is skipped; calls stays 0 ``` This is a frequent source of subtle bugs when someone relies on the right-hand side always running. ## Contrast with non-short-circuiting & and | Java also has `&` and `|`, which on booleans compute the same AND/OR but **always evaluate both operands** (no short-circuit). That difference is its own topic, but the headline is: use `&&`/`||` in conditions; reserve `&`/`|` for the rare case you genuinely want both sides evaluated (or for bitwise math on integers). ## Mental model Read `&&` as "and, but only check the right if the left was true"; read `||` as "or, but only check the right if the left was false". The expression is evaluated **left to right**, and evaluation stops the instant the answer is locked in.

  • Why must the null check come before the method call in obj != null && obj.method()?
    Because evaluation is left-to-right and only short-circuits after the left side. If you put the call first and obj is null, it runs immediately and throws an NPE before the null check is ever reached.
  • Does short-circuiting change the boolean result compared to evaluating both sides?
    No — the final boolean value is identical to a full evaluation. Only whether the right operand is executed (and its side effects) differs.

It's like a checklist where you stop early. To enter a building you need keycard AND PIN (&&) — if your keycard fails, the guard doesn't even ask for the PIN. To win a prize you need a winning ticket OR a coupon (||) — if your ticket already wins, nobody checks the coupon.

saying these in an interview costs you the question

  • Saying short-circuiting changes the truth value — it only changes whether the right side runs
  • Relying on a side effect in the right operand that gets skipped
  • Putting the method call before the null check and assuming it's safe
  • Thinking evaluation can go right-to-left

context