Logical Operators
In short: Operators for combining several boolean expressions: && (AND), || (OR), and ! (negation).
In more detail: && and || in Java evaluate with “short-circuiting” (short-circuit evaluation): for a && b, b isn’t checked at all if a is already false — useful for safely chaining, for example, a null check before a field access (obj != null && obj.getValue() > 0).
In Depth
String text = null;
// Without short-circuiting, text.length() would throw a NullPointerException
if (text != null && text.length() > 0) {
System.out.println("Not empty");
}
// || works the same way in reverse: b isn't checked if a is already true
boolean isWeekend(int day) {
return day == 6 || day == 7; // for day==6, "day == 7" isn't evaluated at all
}
// Non-short-circuiting variants also exist: & and |
// ALWAYS evaluate both sides, even if the first already decides - rarely used
boolean both = (a() & b()); // b() runs even if a() is already falseShort-circuit evaluation is more than a pure performance optimisation — it’s a central safety pattern for AVOIDING errors, by placing the “dangerous” check only after a protective precondition (object != null && object.method()). The rarely used non-short-circuiting variants & and | (with no doubling), by contrast, always evaluate both sides, which can occasionally be desired for method calls with side effects (e.g. both methods should run in any case, regardless of the first one’s result) — but in everyday code, &&/|| are the overwhelming rule.
XOR and the bitwise operator ^
Besides AND/OR/NOT, there’s also “exclusive OR” (XOR, ^), which returns true when EXACTLY ONE of the two sides is true (not both, not neither): true ^ true is false, true ^ false is true. XOR has no short-circuit counterpart, since both sides necessarily have to be known for the result — a common use case is toggling a boolean state (toggled = toggled ^ true; flips the value on every call).
Common beginner mistake: &/| instead of &&/||
An easy-to-miss typo is using the single (non-short-circuiting) operators &/| instead of the double &&/|| — the code usually still compiles without errors, since both operator pairs are valid on boolean values, but without short-circuit protection, a check that’s actually meant to be guarded, like text != null & text.length() > 0, can still throw a NullPointerException for text == null, because text.length() is always executed.
See also: Operators, Comparison Operators, if Statement