Logical, Bitwise, Unary & Ternary Operators
Logical Operators (&&, ||, !) ยท Short-Circuit Evaluation ยท Prefix vs Postfix (++x / x++) ยท Ternary Operator (? :) ยท Bitwise Operators ยท Operator Precedence Table
Comprehensive masterclass on advanced Java operators: boolean logical operations with short-circuit evaluation, memory differences between prefix and postfix increment, the ternary conditional expression, low-level bitwise manipulation, and the complete operator precedence hierarchy.
1. Logical Operators & Short-Circuit Evaluation
Logical operators combine multiple boolean expressions:
| Operator | Name | Logic |
|---|---|---|
| **`&&`** |
true ONLY IF both operands are true. |
| || | Logical OR (Short-Circuit) | Returns true IF AT LEAST ONE operand is true. |
| ! | Logical NOT (Inversion) | Reverses truth value (!true -> false, !false -> true). |
The Power of Short-Circuit Evaluation:
-&& (AND): If the left operand is false, the overall result is guaranteed to be false. The JVM skips evaluating the right operand entirely!
- || (OR): If the left operand is true, the overall result is guaranteed to be true. The JVM skips evaluating the right operand!
This prevents runtime NullPointerException crashes by safely guarding calls:
String user = null;
// Safe: left condition is false, so user.length() is NEVER called!
if (user != null && user.length() > 0) {
System.out.println("Valid user");
}2. Increment & Decrement: Prefix (`++x`) vs Postfix (`x++`)
The increment (++) and decrement (--) operators modify a variable by 1:
+-----------------------------------------------------------------------------------+
| PREFIX vs POSTFIX INCREMENT |
+-----------------------------------------------------------------------------------+
| 1. PREFIX (++x): "UPDATE FIRST, USE SECOND" |
| int x = 5; |
| int y = ++x; // Step 1: x increments to 6. Step 2: y is assigned 6. |
| (x = 6, y = 6) |
+-----------------------------------------------------------------------------------+
| 2. POSTFIX (x++): "USE FIRST, UPDATE SECOND" |
| int a = 5; |
| int b = a++; // Step 1: b is assigned old value 5. Step 2: a increments to 6. |
| (a = 6, b = 5) |
+-----------------------------------------------------------------------------------+3. Ternary Conditional Operator (`? :`)
The Ternary Operator is a concise one-line shorthand for a simple if-else statement that returns a value:
variable = (condition) ? expressionIfTrue : expressionIfFalse;int score = 85;
String status = (score >= 50) ? "PASS" : "FAIL";
int a = 10, b = 25;
int max = (a > b) ? a : b; // Evaluates to 25
4. Bitwise Operators & Bit Shifts
Bitwise operators perform direct binary bit manipulation on integer types:
| Operator | Name | Bit Operation |
|---|---|---|
| **`&`** |
| | Bitwise OR | Bit is 1 if either corresponding bit is 1. |
| ^ | Bitwise XOR | Bit is 1 if corresponding bits are DIFFERENT. |
| ~ | Bitwise NOT (Invert) | Inverts all bits (0 becomes 1, 1 becomes 0). |
| << | Left Shift | Shifts bits left, filling with 0 ($x imes 2^n$). |
| >> | Signed Right Shift | Shifts bits right, preserving sign bit ($x / 2^n$). |
| >>> | Unsigned Right Shift | Shifts bits right, always filling MSB with 0. |
5. Complete Operator Precedence & Associativity Table
When multiple operators appear in one expression, Java evaluates them according to strict precedence (highest to lowest):
| Rank | Operator Category | Operators | Associativity |
|---|---|---|---|
| **1 (Highest)** |
(), [], ., x++, x-- | Left to Right |
| 2 | Unary Prefix | ++x, --x, +, -, !, ~, (type) | Right to Left |
| 3 | Multiplicative | *, /, % | Left to Right |
| 4 | Additive | +, - | Left to Right |
| 5 | Shift | <<, >>, >>> | Left to Right |
| 6 | Relational | <, <=, >, >=, instanceof | Left to Right |
| 7 | Equality | ==, != | Left to Right |
| 8 | Bitwise AND / XOR / OR | &, ^, | | Left to Right |
| 9 | Logical AND / OR | &&, || | Left to Right |
| 10 | Ternary Conditional | ? : | Right to Left |
| 11 (Lowest) | Assignment | =, +=, -=, *=, /=, %= | Right to Left |
Beginner Example & Code Anatomy
public class Main {
public static void main(String[] args) {
// 1. Short-Circuit Logical Evaluation
int age = 22;
boolean hasVoterCard = true;
boolean canVote = (age >= 18) && hasVoterCard;
System.out.println("Voting Eligibility: " + canVote);
// 2. Prefix vs Postfix Increment
int p = 10;
int q = ++p; // Prefix: p becomes 11, q receives 11
System.out.println("Prefix (p, q) : p=" + p + ", q=" + q);
int m = 10;
int n = m++; // Postfix: n receives 10, m becomes 11
System.out.println("Postfix (m, n) : m=" + m + ", n=" + n);
// 3. Ternary Operator
double cartTotal = 1500.00;
double shippingFee = (cartTotal >= 1000.00) ? 0.00 : 50.00;
System.out.println("Cart: โน" + cartTotal + " | Shipping Fee: โน" + shippingFee);
// 4. Bitwise Operations
int bitA = 0b0101; // 5 in binary
int bitB = 0b0011; // 3 in binary
System.out.println("
--- Bitwise Operations (5 & 3) ---");
System.out.println("5 & 3 (AND) : " + (bitA & bitB)); // 0001 = 1
System.out.println("5 | 3 (OR) : " + (bitA | bitB)); // 0111 = 7
System.out.println("5 ^ 3 (XOR) : " + (bitA ^ bitB)); // 0110 = 6
System.out.println("5 << 1 (Shift Left * 2): " + (bitA << 1)); // 10
}
}
๐ Line-by-Line Code Explanation
(age >= 18) && hasVoterCard
Logical AND: returns true only if both age >= 18 and hasVoterCard are true.
int q = ++p;
Prefix increment: increments p to 11 first, then assigns 11 to q.
int n = m++;
Postfix increment: assigns current value 10 to n first, then increments m to 11.
(cartTotal >= 1000.00) ? 0.00 : 50.00
Ternary conditional: evaluates to 0.00 if cart is >= 1000, otherwise evaluates to 50.00.
Practical Real-World Example
public class AccessControlDemo {
public static void main(String[] args) {
boolean isAuthenticated = true;
boolean isAdmin = false;
boolean hasSpecialPermission = true;
// Enterprise authorization rule:
// User must be authenticated AND (be an Admin OR have special permission)
boolean hasAccess = isAuthenticated && (isAdmin || hasSpecialPermission);
String accessBadge = hasAccess ? "[ACCESS GRANTED] Level 2 Clearance" : "[ACCESS DENIED]";
System.out.println("Security Check Result: " + accessBadge);
}
}
- Using single & instead of && for conditionals: Single & evaluates BOTH sides without short-circuiting, which can trigger NullPointerException if guarding null objects.
- Complex increment expressions: Writing "int z = x++ + ++x;" leads to unreadable code and subtle bugs. Keep increment operations on isolated lines.
- Over-nesting ternary operators: While (a ? (b ? c : d) : e) is valid syntax, deeply nested ternaries reduce readability. Use if-else if logic exceeds one level.
Test your understanding by writing the code directly in your editor or running in our online Java compiler:
// Coding Challenge:
// Given 3 numbers: a = 45, b = 78, c = 32:
// 1. Use nested ternary operators to find the largest of three numbers (largest)
// 2. Print: "Largest number is: 78"
public class Main {
public static void main(String[] args) {
int a = 45, b = 78, c = 32;
// TODO: Find maximum using ternary operator
}
}
๐ก Frequently Asked Questions & Interview Insights
โ What is the performance difference between bitwise shift (x << 1) and multiplication (x * 2)?
In modern Java JIT compilers, (x * 2) is automatically optimized to bit shift machine instructions at compile-time. Use arithmetic multiplication for mathematical clarity, and bit shifts when manipulating raw binary protocol flags.
โ Why does ++x operate Right-to-Left?
Unary operators bind directly to their immediate right operand, evaluating before lower-priority additive or assignment operations.
โ What is the unsigned right shift (>>>)?
The standard right shift (>>) preserves the sign bit (fills with 1 for negative numbers), while unsigned right shift (>>>) always shifts in zeros regardless of whether the number is positive or negative.
๐ Quick Chapter Recap
- && and || perform short-circuit evaluation, skipping right operands when outcomes are predetermined.
- Prefix (++x) increments before value retrieval; Postfix (x++) retrieves old value before incrementing.
- Ternary operator (condition ? valTrue : valFalse) provides a clean inline return expression.
- Operator precedence controls execution ordering; use parentheses () to enforce explicit intent.