Java Logical Operators

In the last lesson you learned about Java relational operators. Real rules like β€œlet the user in if they are over 18 and they agreed to the terms” need two checks joined together. Java gives you logical operators for exactly this.

πŸ€” Why combine conditions?

A single comparison can ask only one thing. But most real decisions depend on several things at once:

  • A login. Username correct and password correct.
  • A discount. Cart total over 1000 or the person is a member.
  • A warning banner. Show it when the user is not logged in.

Logical operators are the glue. They take the true/false that comparisons hand you and fold them into one final answer your if acts on.

πŸ”— The three logical operators

Java has three logical operators. Here is a quick map, then we take them one at a time.

Operator Name True when…
&& AND Both sides are true
|| OR At least one side is true
! NOT Flips true to false and false to true

One thing to keep in mind: && and || work on two values (left and right). The ! operator works on just one.

βœ… The AND operator (&&)

The AND operator &&:

  • Is true only when both sides are true.
  • Is false the moment any one side is false.
  • Acts like a door with two locks: you need both keys, or it stays shut.

This code checks an age and a terms agreement, then prints whether both are satisfied.

int age = 20;
boolean agreedToTerms = true;
System.out.println(age >= 18 && agreedToTerms);

Reading it step by step:

  • age >= 18 is true (20 is at least 18).
  • agreedToTerms is true.
  • Both true, so && gives true. The user gets in.

Output

true

Now flip one value. Suppose the user did not agree to the terms.

int age = 20;
boolean agreedToTerms = false;
System.out.println(age >= 18 && agreedToTerms);

The age check still passes, but agreedToTerms is now false. With &&, one false side sinks the whole result. The login is blocked.

Output

false

πŸ”΅ The OR operator (||)

The OR operator ||:

  • Is true when at least one side is true.
  • Is false only when both sides are false, so it is easy to satisfy.
  • Acts like a club door that opens with either a ticket or a membership card.

This code checks the cart total and the membership, then prints whether the discount applies.

double cartTotal = 500;
boolean isMember = true;
System.out.println(cartTotal > 1000 || isMember);

Reading it step by step:

  • cartTotal > 1000 is false (500 is not over 1000).
  • isMember is true.
  • One side is true, and for || that is enough. So the result is true. The discount applies.

Output

true

|| gives false only when both sides fail at once: a small cart and a non-member.

🚫 The NOT operator (!)

The NOT operator !:

  • Works on a single value, not two.
  • Flips it: true becomes false, false becomes true.
  • Sits in front of the value, like !isLoggedIn, read as β€œnot logged in”.

This code checks whether someone is logged in, then flips that to decide if the warning should show.

boolean isLoggedIn = false;
System.out.println(!isLoggedIn);

Reading it step by step:

  • isLoggedIn holds false.
  • The ! flips that false into true.
  • So !isLoggedIn is true, your cue to show the β€œplease log in” warning.

Output

true

Caution

! is one tiny character, so it is easy to miss. When a condition acts the opposite of what you expect, check whether a ! snuck in or went missing.

πŸ“‹ The truth tables

A truth table lists every combination of inputs and shows the answer for each. Here is one per operator.

For AND &&, both must be true, so the answer is true in only one row.

A B A && B
true true true
true false false
false true false
false false false

For OR ||, any one true is enough, so the answer is false in only one row.

A B A || B
true true true
true false true
false true true
false false false

And NOT ! is the simplest table: one input, flipped.

A !A
true false
false true

Quick memory trick: for && the only true is both-true; for || the only false is both-false.

⚑ Short-circuit evaluation

Short-circuit evaluation means Java reads left to right and stops the moment the answer is certain:

  • With &&, a false left side already settles the result as false, so Java skips the right side.
  • With ||, a true left side already settles it as true, so Java skips the right side.
  • This is faster (an expensive call on the right gets skipped) and safer (a guard on the left protects a risky check on the right).

That last point is the big one. This code shows the classic null-guard on a name that is null.

String name = null;
if (name != null && name.length() > 0) {
System.out.println("Name is set");
} else {
System.out.println("No name");
}

Reading it step by step:

  • The left side name != null runs first and is false.
  • A false left side settles the &&, so Java stops there.
  • It never runs name.length(), which would crash with a NullPointerException on a null value.

Output

No name

Order matters: the guard name != null sits on the left on purpose so it runs first and protects the call on the right.

|| has its own safe pattern: it can short-circuit out early when something is already true.

boolean isAdmin = true;
if (isAdmin || hasExpensivePermissionCheck()) {
System.out.println("Access granted");
}

Since isAdmin is true, the || is already settled. So Java skips hasExpensivePermissionCheck() entirely, saving real time when the cheap reason is enough.

πŸ”€ The difference between && and &

Java also has a single & and a single |. For booleans:

  • They do not short-circuit; they always check both sides.
  • That mostly does nothing, but it bites when the right side has a guard depending on the left.

See what goes wrong here.

String name = null;
// ❌ Single & checks BOTH sides, so length() still runs and crashes
if (name != null & name.length() > 0) {
System.out.println("Name is set");
}

Even though name != null is false, the single & still runs name.length() and crashes. The double && would have skipped it. So for conditions, always use && and ||. The single & and | are for bit-level math, a different topic.

βž• Combining conditions with brackets

You can chain more than two checks. But once you mix && and || on one line, use brackets to keep the grouping clear:

  • && binds tighter than ||, like multiply binds tighter than add in maths.
  • Without brackets, the && parts group first, which is not always what you meant.
  • Brackets remove all doubt.

This range check uses brackets to say β€œthe score is between 0 and 100, and the user is active”.

int score = 85;
boolean isActive = true;
if ((score >= 0 && score <= 100) && isActive) {
System.out.println("Valid active score");
}

The brackets group the range test as one idea, then join it with isActive. Reading it back: a valid range, and the user is active.

Output

Valid active score

Here brackets really change the meaning: free shipping for a large order, or for a premium member in a supported country.

double total = 200;
boolean isPremium = true;
boolean inSupportedCountry = true;
if (total > 500 || (isPremium && inSupportedCountry)) {
System.out.println("Free shipping");
}

The brackets keep isPremium && inSupportedCountry together as one reason. Then || offers two paths: a big order, or a premium member in a supported country. The order is only 200, so the first path fails, but the second passes. Shipping is free.

Output

Free shipping

Tip

Even when brackets are not strictly required, adding them makes mixed logic easier to read. Your future self will thank you when revisiting the code months later.

⚠️ Common Mistakes

A few slip-ups trip up almost everyone at first.

Using single & or | for conditions. These do not short-circuit, so a guard on the left will not protect the right side. Use the double forms.

// ❌ Avoid: single & runs both sides, so a null guard does not protect you
// if (user != null & user.isActive()) ...
// βœ… Good: double && short-circuits and stops at the false left side
if (user != null && user.isActive()) {
System.out.println("Active user");
}

Getting AND and OR backwards. AND needs everything true. OR needs just one true. Swapping them quietly changes your whole rule.

// ❌ Avoid: OR lets anyone over 18 in, even without agreeing
// if (age >= 18 || agreedToTerms) ...
// βœ… Good: AND requires both to be true
if (age >= 18 && agreedToTerms) {
System.out.println("Welcome");
}

Forgetting the safe order with &&. The guard check has to come first. Put the risky check after it, so short-circuiting can protect it.

// ❌ Avoid: length() runs before the null check, so this can crash
// if (name.length() > 0 && name != null) ...
// βœ… Good: the null guard is on the left and runs first
if (name != null && name.length() > 0) {
System.out.println("Name is set");
}

βœ… Best Practices

A few habits keep your logic clean and safe:

  • Use && and ||, not & and |. The double forms are built for combining conditions, and they short-circuit.
  • Put guard checks first. With &&, a null check or a zero check on the left keeps the right side safe to run.
  • Use brackets for mixed logic. When && and || appear together, brackets like (a && b) || c spell out exactly what you mean.
  • Read conditions out loud. If β€œover 18 and agreed” matches your rule, you picked the right operator. If it sounds wrong spoken, the code is probably wrong too.
  • Avoid double negatives. !isNotReady is hard to read. Name the variable for the positive case, like isReady, and life gets simpler.

🧩 What You’ve Learned

Quick recap of the key points:

  • βœ… Logical operators combine boolean values into one final true or false.
  • βœ… && (AND) is true only when both sides are true.
  • βœ… || (OR) is true when at least one side is true.
  • βœ… ! (NOT) flips a single boolean to its opposite.
  • βœ… Short-circuit evaluation stops as soon as the answer is known, which also protects risky checks placed on the right of &&.
  • βœ… Single & and | do not short-circuit, so stick with the double forms for conditions.
  • βœ… Brackets make mixed && and || logic clear and predictable.

Check Your Knowledge

Test what you learned. Pick an answer for each question, then click Check.

  1. 1

    When is A && B true?

    Why: AND (&&) is true only when both sides are true. If either is false, the result is false.

  2. 2

    When is A || B true?

    Why: OR (||) is true when at least one side is true. It is only false when both are false.

  3. 3

    What does the ! operator do?

    Why: NOT (!) reverses a boolean, turning true into false and false into true.

  4. 4

    Why does name != null && name.length() > 0 not crash when name is null?

    Why: With &&, if the left side is false, Java skips the right side, so length() is never called on null.

πŸš€ What’s Next?

You can now build rich conditions. Next we look at operators that work on a single value. They let you increment, decrement, and flip a sign with one short symbol.

Java Unary Operators

Share & Connect