Back to Operators & Expressions
Q3Question 3 of 9

What is the difference between && and & in Java?

Key Concepts
  • && is short-circuit logical AND: skips the right side if the left is false
  • || is short-circuit logical OR: skips the right side if the left is true
  • & and | always evaluate both sides – no short-circuit, even for boolean operands
  • & and | on integers perform bitwise AND/OR on each pair of bits
  • Short-circuiting matters for null guards: account != null && account.isActive() is safe with &&, crashes with &
  • Use && and || by default – use & and | only for bitwise operations on integers

Definition

&& short-circuits (skips right side if left is false), & always evaluates both sides. For boolean logic use &&/||. For bit manipulation on integers use &/|.

Two families of AND/OR:

  • && and || (short-circuit logical). && skips the right operand if the left is false (because false AND anything is false). || skips the right if the left is true (because true OR anything is true). This prevents unnecessary evaluation and protects null guards.
  • & and | (non-short-circuit / bitwise). On boolean operands, they compute the same result but always evaluate both sides. On integer operands, they perform bitwise operations on each pair of bits.

A loan officer checks two conditions: is the account active AND is the balance sufficient? With &&, if the account is not active, she stops immediately (short-circuit) – no need to check the balance. With &, she checks both conditions even if the first already failed. If checking the balance requires opening a locked vault (expensive operation) or the account is null (crash), short-circuiting saves time and prevents errors.

Understanding the Concepts

What is short-circuit evaluation?

Short-circuit means the second operand is not evaluated if the first operand already determines the result.

JAVA
// && short-circuits: if left is false, right is NEVER evaluated
boolean result = false && expensiveCheck();  // expensiveCheck() NOT called

// || short-circuits: if left is true, right is NEVER evaluated
boolean result2 = true || expensiveCheck();  // expensiveCheck() NOT called

This is important for performance (skip expensive operations) and safety (skip operations that would crash).

Why does short-circuiting matter for null guards?

The most common use of short-circuiting is null-safe access:

JAVA
Account account = findAccount("SAV2001");  // might return null

// SAFE with &&: if account is null, isActive() is never called
if (account != null && account.isActive()) {
    System.out.println("Account is active");
}

// CRASH with &: both sides always evaluated, even if account is null
// if (account != null & account.isActive()) {  // NPE if account is null!

With &&, the null check on the left protects the method call on the right. With &, both sides are always evaluated, so account.isActive() is called on null and throws NullPointerException.

How does & work on integers (bitwise AND)?

When used with integer operands, & performs bitwise AND – each bit in the result is 1 only if both corresponding input bits are 1.

JAVA
int permissions = 0b1010;  // binary: has read (bit 3) and execute (bit 1)
int readMask    = 0b1000;  // binary: read bit

boolean canRead = (permissions & readMask) != 0;  // true: bit 3 is set
System.out.println(canRead);  // true

// In banking: checking feature flags
int accountFlags = 0b0111;  // overdraft + international + premium
int overdraftBit = 0b0001;
boolean hasOverdraft = (accountFlags & overdraftBit) != 0;  // true

How does | work on integers (bitwise OR)?

JAVA
// Combining flags with bitwise OR
int flags = 0;
flags = flags | 0b0001;  // set overdraft bit
flags = flags | 0b0100;  // set premium bit
System.out.println(Integer.toBinaryString(flags));  // 101

What about ^ (XOR) and ~ (NOT)?

JAVA
// XOR: bits differ → 1, same → 0
int a = 0b1100;
int b = 0b1010;
System.out.println(Integer.toBinaryString(a ^ b));  // 0110

// NOT: flips all bits
int c = 0b00001111;
System.out.println(Integer.toBinaryString(~c));  // 11111111111111111111111111110000

What about shift operators?

JAVA
// Left shift: multiply by 2^n
int amount = 100;
System.out.println(amount << 1);   // 200 (100 * 2)
System.out.println(amount << 3);   // 800 (100 * 8)

// Right shift (signed): divide by 2^n, preserves sign
int negative = -100;
System.out.println(negative >> 1);  // -50

// Unsigned right shift: fills with 0, ignores sign
System.out.println(negative >>> 1); // 2147483598 (large positive)

When should you use & vs &&?

| Use case | Operator | Why |
|---|---|---|
| Boolean logic (if conditions) | && / || | Short-circuit protects null guards, saves work |
| Bitwise operations on integers | & / | / ^ / ~ | Bit manipulation, flag checks |
| Force evaluation of both sides (rare) | & / | on booleans | Only if both sides have required side effects |

What are common mistakes?

  • Using & instead of && for null guards. account != null & account.isActive() crashes on null. Always use &&.
  • Using && for bitwise operations. flags && mask does not compile if flags is int. Use &.
  • Side effects in short-circuited expressions. if (true || counter++) never increments counter. Do not put side effects in boolean expressions.
  • Confusing >> with >>>. Signed right shift preserves the sign bit. Unsigned right shift fills with zeros. Use >>> for hash code calculations.

What should a senior engineer know?

  • Bitwise operations are used in permission systems. Unix file permissions, feature flags, and database bit columns all use & and | for efficient multi-flag storage and checking.
  • EnumSet uses bitwise operations internally. EnumSet.of(READ, WRITE) is backed by a long bitmask for efficiency.
  • Shift operators are used in hash functions. HashMap.hash() uses h ^ (h >>> 16) to spread hash bits.
  • Bitwise AND with mask for modulo power-of-2. index & (length - 1) is equivalent to index % length when length is a power of 2, and is faster. HashMap uses this for bucket indexing.

Visual Overview

DIAGRAM
  && (short-circuit AND):          & (non-short-circuit / bitwise):
    left is false?                   always evaluates BOTH sides
    → skip right, return false       on booleans: same result, no skip
    left is true?                    on integers: bit-by-bit AND
    → evaluate right, return result

  Null guard example:
    account != null && account.isActive()   → safe (skips if null)
    account != null &  account.isActive()   → NPE! (evaluates both)

  Bitwise AND on integers:
    0b1010 & 0b1100 = 0b1000  (each bit: 1 only if both are 1)

  Shift operators:
    100 << 1  = 200  (multiply by 2)
    100 >> 1  = 50   (divide by 2, signed)
    -1 >>> 1  = MAX  (unsigned, fill with 0)

Key Takeaway

The && and || operators short-circuit: they skip the right operand when the left already determines the result. The & and | operators always evaluate both sides. On boolean operands, the result is the same, but the evaluation behavior differs. On integer operands, & and | perform bitwise operations on each pair of bits.

The most important practical consequence is null guards. Writing account != null && account.isActive() is safe because if account is null, the right side is never evaluated. Changing && to & would crash with NullPointerException because & always evaluates both sides.

Use && and || for all boolean logic in if conditions, loop conditions, and ternary expressions. Use &, |, ^, and ~ only for bitwise operations on integers – permission flags, feature masks, and hash calculations. The only time you would use & on booleans is when both sides must be evaluated for their side effects, which is rare and usually a code smell.

One sentence to remember: && short-circuits and is safe for null guards; & always evaluates both sides and is for bitwise operations on integers.

---

Share
Use ← → arrow keys to navigate