W3docs

Java Logical Operators

Combine boolean expressions with &&, ||, and !, and understand short- circuit evaluation in Java.

Logical operators combine boolean values into more complex tests. Java provides three: AND (&&), OR (||), and NOT (!). The key feature of && and || — that they short-circuit — is what makes them safe to use even when one operand might throw.

The three operators

OperatorNameResult
&&ANDtrue only if both operands are true
||ORtrue if at least one operand is true
!NOTflips a boolean!true is false
boolean isAdult = age >= 18;
boolean hasTicket = ticket != null;

if (isAdult && hasTicket) {
    enterCinema();
}

if (isHoliday || isWeekend) {
    sleepIn();
}

if (!isLoggedIn) {
    redirectToLogin();
}

Short-circuit evaluation

&& evaluates its right-hand side only if the left-hand side is true. If the left is false, the result is already known and the right is skipped:

boolean leftFalse = false && expensiveCall();   // expensiveCall() never runs

|| mirrors this — it skips the right-hand side if the left is true:

boolean leftTrue = true || expensiveCall();     // expensiveCall() never runs

This is essential for null checks:

if (user != null && user.isActive()) { ... }

If user is null, the right-hand side is skipped — no NullPointerException. Reversing them would crash:

if (user.isActive() && user != null) { ... }   // NPE when user is null

The rule of thumb: put the cheapest, safest, or most-likely-to-fail check first.

Non-short-circuit & and |

Java also has & and | (single character). On booleans they compute the same AND/OR, but they always evaluate both sides. You'll rarely want this — it exists mostly for the bitwise variants on integers (covered in Java Bitwise Operators).

boolean a = false & expensiveCall();   // expensiveCall() DOES run
boolean b = true | expensiveCall();    // expensiveCall() DOES run

If you find yourself reaching for & or | on booleans, you almost certainly want && and ||.

Combining operators

You can chain logical operators to build any boolean test:

boolean validAge = age >= 13 && age < 120;
boolean validUser = (name != null && !name.isBlank()) && validAge;

if (isWeekend || (isHoliday && !isWorkRequired)) {
    relax();
}

! binds the tightest, then &&, then ||. When mixing them, add parentheses for clarity even where they aren't strictly needed.

Common patterns

Range checks — combine two relational tests with &&:

if (x >= 0 && x < array.length) { ... }

Whitelist — combine several equals with ||:

if (status.equals("READY") || status.equals("RUNNING") || status.equals("DONE")) { ... }

(For long lists, prefer List.of(...).contains(status) or a switch.)

Guard clauses — fail fast with !:

if (!isAuthenticated) {
    throw new AuthException();
}
// ... main logic ...

De Morgan's laws

When you negate a combined expression, the operators flip:

!(a && b)    is the same as    !a || !b
!(a || b)    is the same as    !a && !b

So !(age >= 18 && hasId) is age < 18 || !hasId. Most readers prefer the positive form when possible — refactor toward what's easiest to read.

A demonstration

java— editable, runs on the server

What's next

Java Bitwise Operators — for the rare moments when you really do need to manipulate raw bits.

Practice

Practice

Which expression safely checks that user isn't null AND user.isActive() returns true?