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
| Operator | Name | Result |
|---|---|---|
&& | AND | true only if both operands are true |
|| | OR | true if at least one operand is true |
! | NOT | flips 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 runsThis 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 nullThe 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 runIf 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 && !bSo !(age >= 18 && hasId) is age < 18 || !hasId. Most readers prefer the positive form when possible — refactor toward what's easiest to read.
A demonstration
What's next
Java Bitwise Operators — for the rare moments when you really do need to manipulate raw bits.
Practice
Which expression safely checks that user isn't null AND user.isActive() returns true?