Operators
Arithmetic, logical, bitwise, comparison operators and short-circuit evaluation
Operators and Expressions
Java operators and expressions: arithmetic, relational, logical, bitwise, assignment, ternary, instanceof operators, precedence, and evaluation order.
1. Definition
What is it?
An operator is a symbol that performs an operation on one or more operands and produces a result (value). An expression is a combination of operators and operands that evaluates to a single value.
Why does it matter?
- Fundamental building block: every algorithm, condition, and loop relies on operators
- Performance: choosing the right operator (e.g., bitwise shift vs. multiplication) can make a meaningful difference
- Readability: understanding precedence and short-circuit evaluation is essential for bug-free code
Where does it fit?
Operators belong to the syntactic foundation layer of Java â directly above types and variables, and below control structures.
2. Core Concepts
2.1 Arithmetic Operators
| Operator | Description | Example | Result |
|---|---|---|---|
+ |
Addition | 5 + 3 |
8 |
- |
Subtraction | 5 - 3 |
2 |
* |
Multiplication | 5 * 3 |
15 |
/ |
Division | 7 / 2 |
3 (integer division!) |
% |
Modulo (remainder) | 7 % 2 |
1 |
++ |
Increment | i++ / ++i |
pre/post increment |
-- |
Decrement | i-- / --i |
pre/post decrement |
â ïž Integer division: when both operands are integers, the result is an integer (the decimal part is truncated).
2.2 Relational / Comparison Operators
| Operator | Description | Example |
|---|---|---|
== |
Equal to | a == b |
!= |
Not equal to | a != b |
> |
Greater than | a > b |
< |
Less than | a < b |
>= |
Greater than or equal | a >= b |
<= |
Less than or equal | a <= b |
đ For primitives,
==compares values. For objects,==compares references.
2.3 Logical Operators
| Operator | Description | Short-circuit? |
|---|---|---|
&& |
Logical AND | â
Yes â if left is false, right is not evaluated |
|| |
Logical OR | â
Yes â if left is true, right is not evaluated |
! |
Logical NOT | â |
& |
Logical AND (eager) | â No |
| |
Logical OR (eager) | â No |
2.4 Bitwise Operators
| Operator | Description | Example |
|---|---|---|
& |
Bitwise AND | 0b1010 & 0b1100 â 0b1000 |
| |
Bitwise OR | 0b1010 | 0b1100 â 0b1110 |
^ |
Bitwise XOR | 0b1010 ^ 0b1100 â 0b0110 |
~ |
Bitwise NOT (complement) | ~0b1010 â 0b...0101 |
<< |
Left shift | 1 << 3 â 8 |
>> |
Signed right shift | -8 >> 2 â -2 |
>>> |
Unsigned right shift | -1 >>> 28 â 15 |
2.5 Assignment Operators
| Operator | Equivalent |
|---|---|
= |
Simple assignment |
+= |
a = a + b |
-= |
a = a - b |
*= |
a = a * b |
/= |
a = a / b |
%= |
a = a % b |
&= |
a = a & b |
|= |
a = a | b |
^= |
a = a ^ b |
<<= |
a = a << b |
>>= |
a = a >> b |
>>>= |
a = a >>> b |
đ Compound assignment operators (e.g.,
+=) include an implicit cast:short s = 1; s += 1;â compiles, buts = s + 1;â compile error (int â short narrowing).
2.6 Ternary Operator (Conditional Expression)
result = (condition) ? valueIfTrue : valueIfFalse;
This is the only three-operand (ternary) operator in Java.
2.7 instanceof Operator
if (obj instanceof String s) { // pattern matching (Java 16+)
System.out.println(s.length());
}
null instanceof Anythingâ alwaysfalse- Since Java 16, pattern matching allows declaring a variable inside instanceof
2.8 Operator Precedence Table
| Priority | Operator(s) | Associativity |
|---|---|---|
| 1 (highest) | () [] . |
Left to right |
| 2 | ++ -- (postfix) |
Left to right |
| 3 | ++ -- (prefix) + - (unary) ~ ! |
Right to left |
| 4 | (type) cast |
Right to left |
| 5 | * / % |
Left to right |
| 6 | + - |
Left to right |
| 7 | << >> >>> |
Left to right |
| 8 | < <= > >= instanceof |
Left to right |
| 9 | == != |
Left to right |
| 10 | & |
Left to right |
| 11 | ^ |
Left to right |
| 12 | | |
Left to right |
| 13 | && |
Left to right |
| 14 | || |
Left to right |
| 15 | ? : |
Right to left |
| 16 (lowest) | = += -= etc. |
Right to left |
3. Practical Usage
When to Use Which Operator?
| Task | Recommended | Why? |
|---|---|---|
| Even/odd check | n % 2 == 0 |
Simple, readable |
| Multiply/divide by power of 2 | n << 1 / n >> 1 |
Performance (though JIT optimizes anyway) |
| Null-safe check | obj != null && obj.method() |
Short-circuit guards against NullPointerException |
| Simple if-else value | Ternary ? : |
More concise, but don't nest! |
| Flag management | Bitwise &, |, ^ |
Memory-efficient, fast |
| Type checking | instanceof + pattern matching |
Modern Java 16+ idiom |
4. Code Examples
4.1 Basic Examples
// Integer division â common surprise
int a = 7 / 2; // 3, NOT 3.5!
double b = 7.0 / 2; // 3.5 â at least one operand is double
// Pre vs. post increment
int i = 5;
int x = i++; // x = 5, i = 6 (post: assign first, then increment)
int y = ++i; // y = 7, i = 7 (pre: increment first, then assign)
// Modulo with negative numbers
int mod = -7 % 3; // -1 (result sign follows the dividend's sign)
4.2 Short-Circuit Evaluation
// â
Correct: short-circuit guards against NullPointerException
String name = null;
if (name != null && name.length() > 0) {
System.out.println(name);
}
// â Wrong: & is not short-circuit, will throw NullPointerException!
if (name != null & name.length() > 0) { // đ„ NPE!
System.out.println(name);
}
4.3 Bitwise Flag Management
// Define flags
static final int READ = 0b0001; // 1
static final int WRITE = 0b0010; // 2
static final int EXECUTE = 0b0100; // 4
// Set a flag
int permissions = READ | WRITE; // 0b0011 = 3
// Check a flag
boolean canRead = (permissions & READ) != 0; // true
// Clear a flag
permissions = permissions & ~WRITE; // 0b0001 = 1
// Toggle a flag
permissions = permissions ^ EXECUTE; // 0b0101 = 5
4.4 Ternary â Good and Bad Usage
// â
Simple and readable
String status = (age >= 18) ? "adult" : "minor";
// â Nested ternary â unreadable!
String category = (age < 13) ? "child" : (age < 18) ? "teenager" : "adult";
// â
Use if-else or switch expression instead
String category;
if (age < 13) category = "child";
else if (age < 18) category = "teenager";
else category = "adult";
4.5 Compound Assignment Implicit Cast
short s = 10;
// s = s + 1; // â Compile error! (s + 1 = int, int â short narrowing)
s += 1; // â
OK! += includes implicit cast: s = (short)(s + 1)
byte b = 127;
b += 1; // â
Compiles, BUT overflow! b = -128
5. Trade-offs
| Aspect | Option A | Option B | When to choose? |
|---|---|---|---|
| Readability vs. brevity | if-else |
Ternary ? : |
Ternary for simple one-liner choices; if-else for complex logic |
| Bitwise vs. conventional | n * 2 |
n << 1 |
On modern JVMs there's no real speed difference; n * 2 is more readable |
| Short-circuit vs. eager | && / || |
& / | |
Almost always short-circuit; eager only when both side effects are needed |
| == vs. equals() | == |
.equals() |
== for primitives and reference identity; .equals() for content comparison |
6. Common Mistakes
â 6.1 Integer Division Surprise
double result = 1 / 3; // 0.0, not 0.333!
double correct = 1.0 / 3; // 0.333... â
double alsoCorrect = (double) 1 / 3; // 0.333... â
â 6.2 Precedence Pitfall
// Intent: (a & b) != 0
if (a & b != 0) { } // â Actually: a & (b != 0) â != has higher precedence than &!
if ((a & b) != 0) { } // â
Use parentheses!
â 6.3 == vs. equals on Objects
String s1 = new String("hello");
String s2 = new String("hello");
s1 == s2; // false â different references!
s1.equals(s2); // true â
â 6.4 Pre/Post Increment Side Effects
int i = 0;
int result = i++ + ++i; // â Confusing, looks platform-specific
// Well-defined in Java (result = 0 + 2 = 2), but AVOID this pattern!
â 6.5 Overflow in Compound Assignment
byte b = 127;
b += 1; // -128! No compile-time warning, silent overflow
7. Senior-level Insights
7.1 Absence of Operator Overloading
Unlike C++ and Kotlin, Java does not support operator overloading. The only exception is the + operator for String concatenation, which the compiler rewrites to StringBuilder or invokedynamic (Java 9+).
7.2 Expression Evaluation Order (JLS §15.7)
The Java Language Specification guarantees that operands are evaluated left-to-right. This is not the same as precedence:
int i = 0;
int r = (i = 1) + (i = 2); // r = 1 + 2 = 3, NOT 2 + 2!
// The left operand is evaluated before the right operand
7.3 Numeric Promotion Rules
- If either operand is
doubleâ result isdouble - Otherwise, if either is
floatâ result isfloat - Otherwise, if either is
longâ result islong - Otherwise: both are promoted to
int(even ifbyte+byte!)
byte a = 10, b = 20;
// byte c = a + b; // â Compile error! a + b = int
int c = a + b; // â
7.4 NaN and Infinity Behavior
double nan = Double.NaN;
nan == nan; // false! NaN is never equal to itself
Double.isNaN(nan); // true â
double inf = 1.0 / 0; // Infinity, not ArithmeticException!
int zero = 1 / 0; // đ„ ArithmeticException (integer division)
7.5 Switch Expression vs. Ternary (Java 14+)
// Java 14+ switch expression â more readable than nested ternary
String type = switch (code) {
case 1 -> "admin";
case 2 -> "user";
default -> "guest";
};
8. Glossary
| Term | Definition |
|---|---|
| Operator | A symbol that performs an operation on operand(s) |
| Operand | The value on which an operator acts |
| Expression | A combination of operators and operands that evaluates to a single value |
| Precedence | The priority order in which operators are evaluated |
| Associativity | When precedence is equal, the direction of evaluation (left-to-right or right-to-left) |
| Short-circuit evaluation | Skipping evaluation of the right operand when the result is already determined |
| Bitwise | An operation applied to individual bits |
| Ternary operator | A three-operand conditional expression (? :) |
| Numeric promotion | Automatic conversion of smaller types to larger types during operations |
| Compound assignment | Combined operation and assignment (+=, -=, etc.) with implicit cast |
| instanceof | Type-checking operator, with pattern matching support since Java 16 |
| Unary operator | An operator with a single operand (e.g., !, ~, ++) |
| Binary operator | An operator with two operands (e.g., +, &&) |
9. Cheatsheet
- Integer division:
7 / 2 = 3â use7.0 / 2or explicit cast for decimals - Short-circuit:
&&and||â right side not evaluated if result is already determined - Precedence: when in doubt, use parentheses â
(a & b) != 0 - == vs. equals:
==for primitives,.equals()for objects - Compound assignment:
+=includes implicit cast âs += 1compiles,s = s + 1doesn't (ifsis short/byte) - Numeric promotion:
byte + byte = intâ explicit cast needed to assign back - NaN:
Double.NaN != Double.NaNâ useDouble.isNaN() - instanceof null:
null instanceof Anythingâ alwaysfalse - Bitwise shift:
1 << n= 2âż â useful for flags and powers of two - Ternary: one level deep max â if more complex, use if-else or switch expression
- Evaluation order: JLS guarantees left-to-right evaluation, but don't rely on it with side effects!
- Operator overloading: Java has none â except
+for String concatenation
đź Games
8 questions