Operators
Operators are symbols that perform operations on operands to produce a result. Java groups them by purpose — arithmetic, relational, logical, bitwise, assignment, and a few special operators. Understanding precedence and associativity is essential to predict how complex expressions evaluate.
Arithmetic Operators
These perform standard math on numeric types. Integer division truncates toward zero; % yields the remainder.
int a = 17, b = 5;
System.out.println(a + b); // 22
System.out.println(a - b); // 12
System.out.println(a * b); // 85
System.out.println(a / b); // 3 (integer division)
System.out.println(a % b); // 2 (remainder)
Output:
22
12
85
3
2
Warning: Integer division by zero throws
ArithmeticException. Floating-point division by zero instead producesInfinityorNaN.
The + operator is overloaded for String concatenation: "x" + 1 produces "x1".
Increment and Decrement
++ and -- add or subtract one. Prefix evaluates before use; postfix evaluates after.
int i = 5;
System.out.println(i++); // 5, then i becomes 6
System.out.println(++i); // i becomes 7, prints 7
Relational and Logical Operators
Relational operators (==, !=, <, >, <=, >=) return boolean. Logical operators combine booleans; && and || short-circuit, skipping the right operand when the result is already determined.
int age = 25;
boolean eligible = age >= 18 && age < 65; // true
boolean special = age < 13 || age > 60; // false
String s = null;
if (s != null && s.length() > 0) { // short-circuit avoids NPE
System.out.println("non-empty");
}
Note: Use
==only for primitives. For objects,==compares references; use.equals()to compare values.
Bitwise and Shift Operators
These operate on the binary representation of integer types.
| Operator | Name | Example (a=6, b=3) | Result |
|---|---|---|---|
& | AND | a & b | 2 |
| | OR | a | b | 7 |
^ | XOR | a ^ b | 5 |
~ | NOT | ~a | -7 |
<< | left shift | a << 1 | 12 |
>> | signed right shift | a >> 1 | 3 |
>>> | unsigned right shift | -1 >>> 28 | 15 |
int flags = 0b0101;
flags |= 0b0010; // set a bit -> 0b0111
boolean hasBit = (flags & 0b0100) != 0; // test a bit -> true
System.out.println(flags + " " + hasBit);
Output:
7 true
Assignment Operators
= assigns; compound forms (+=, -=, *=, /=, %=, &=, |=, ^=, <<=, >>=) combine an operation with assignment and include an implicit cast.
int total = 10;
total += 5; // total = total + 5 -> 15
byte b = 10;
b += 300; // compiles: implicit narrowing cast, b becomes 54
Ternary Operator
The only ternary operator, ?:, is a compact conditional expression.
int score = 72;
String grade = score >= 60 ? "Pass" : "Fail";
int max = (a > b) ? a : b;
The instanceof Operator
instanceof tests an object’s runtime type. Pattern matching (Java 16+) binds a variable in the same expression.
Object obj = "hello";
if (obj instanceof String s) { // pattern matching
System.out.println(s.length()); // s is in scope, no cast needed
}
Operator Precedence
Higher rows bind tighter. Within a row, associativity decides grouping.
| Precedence | Operators | Associativity |
|---|---|---|
| 1 (highest) | [] . () (call) | left |
| 2 | ++ -- (postfix) | left |
| 3 | ++ -- + - ! ~ (unary) | right |
| 4 | * / % | left |
| 5 | + - | left |
| 6 | << >> >>> | left |
| 7 | < > <= >= instanceof | left |
| 8 | == != | left |
| 9 | & | left |
| 10 | ^ | left |
| 11 | | | left |
| 12 | && | left |
| 13 | || | left |
| 14 | ?: | right |
| 15 (lowest) | = += -= … | right |
int result = 2 + 3 * 4; // 14, not 20 — * before +
boolean b = 5 > 3 == true; // (5 > 3) == true -> true
Best Practices
- Use parentheses to make intent explicit even when precedence already favors you.
- Prefer
&&/||short-circuiting to guard against null or expensive checks. - Reserve bitwise operators for flags and low-level work; they read poorly elsewhere.
- Keep ternary expressions simple; nest them sparingly to preserve readability.