Operators in Java
Complete guide to Java operators — arithmetic, relational, bitwise, shift, logical, ternary, instanceof, and operator precedence.
Arithmetic Operators
The basic math operators work on numeric types (int, long, double, etc.):
public class ArithmeticDemo {
public static void main(String[] args) {
int a = 17, b = 5;
System.out.println(a + b); // 22 — addition
System.out.println(a - b); // 12 — subtraction
System.out.println(a * b); // 85 — multiplication
System.out.println(a / b); // 3 — integer division (truncates)
System.out.println(a % b); // 2 — modulo (remainder)
// Floating-point division
System.out.println(17.0 / 5); // 3.4
System.out.println((double) a / b); // 3.4 — cast one operand
// Integer overflow wraps around silently
int max = Integer.MAX_VALUE; // 2_147_483_647
System.out.println(max + 1); // -2_147_483_648 (wraps!)
// Use long or Math.addExact() to detect overflow:
// Math.addExact(max, 1); // throws ArithmeticException
}
}
Increment and Decrement
int x = 10;
// Post-increment: use then increment
System.out.println(x++); // 10 — prints x, then x becomes 11
System.out.println(x); // 11
// Pre-increment: increment then use
System.out.println(++x); // 12 — x becomes 12, then prints
System.out.println(x); // 12
// Same logic for decrement (--)
int y = 5;
System.out.println(y--); // 5
System.out.println(y); // 4
Compound Assignment Operators
int n = 20;
n += 5; // n = n + 5 → 25
n -= 3; // n = n - 3 → 22
n *= 2; // n = n * 2 → 44
n /= 4; // n = n / 4 → 11
n %= 3; // n = n % 3 → 2
Relational Operators
Relational operators return boolean:
int a = 10, b = 20;
System.out.println(a == b); // false — equal
System.out.println(a != b); // true — not equal
System.out.println(a < b); // true — less than
System.out.println(a > b); // false — greater than
System.out.println(a <= b); // true — less than or equal
System.out.println(a >= b); // false — greater than or equal
Logical Operators
boolean sunny = true;
boolean warm = false;
// && — AND: both must be true
System.out.println(sunny && warm); // false
// || — OR: at least one must be true
System.out.println(sunny || warm); // true
// ! — NOT: flips the value
System.out.println(!sunny); // false
// Short-circuit evaluation:
// && stops at the first false; || stops at the first true
int[] arr = null;
// Safe because arr != null is checked first
if (arr != null && arr.length > 0) {
System.out.println(arr[0]);
}
Bitwise Operators
Bitwise operators work directly on the binary representation of integers:
public class BitwiseDemo {
public static void main(String[] args) {
int a = 0b1010; // 10
int b = 0b1100; // 12
// & AND — bit is 1 only if both bits are 1
System.out.println(Integer.toBinaryString(a & b)); // 1000 = 8
// | OR — bit is 1 if at least one bit is 1
System.out.println(Integer.toBinaryString(a | b)); // 1110 = 14
// ^ XOR — bit is 1 if the bits differ
System.out.println(Integer.toBinaryString(a ^ b)); // 0110 = 6
// ~ NOT — flips all bits (one's complement)
System.out.println(~a); // -11 (two's complement)
}
}
Common Bitwise Patterns
// Check if a number is even (last bit is 0)
boolean isEven = (n & 1) == 0;
// Check if the k-th bit is set (0-indexed from right)
boolean isSet = (n & (1 << k)) != 0;
// Set the k-th bit
int withBitSet = n | (1 << k);
// Clear the k-th bit
int withBitCleared = n & ~(1 << k);
// Toggle the k-th bit
int toggled = n ^ (1 << k);
// Fast multiply/divide by powers of 2
int doubled = n << 1; // n * 2
int halved = n >> 1; // n / 2
int times8 = n << 3; // n * 8
Shift Operators
int n = 8; // binary: 0000_1000
// << left shift — multiply by 2^k (fills right with 0s)
System.out.println(n << 1); // 16 (8 * 2)
System.out.println(n << 3); // 64 (8 * 8)
// >> signed right shift — divide by 2^k (preserves sign bit)
System.out.println(n >> 1); // 4 (8 / 2)
System.out.println(-8 >> 1); // -4 (sign preserved)
// >>> unsigned right shift — always fills with 0 from left
System.out.println(-8 >>> 1); // 2147483644 (large positive)
// Extracting bytes from an int (common in network/file I/O)
int value = 0xABCD1234;
byte b0 = (byte) (value & 0xFF); // least significant byte: 0x34
byte b1 = (byte) ((value >> 8) & 0xFF); // 0x12
byte b2 = (byte) ((value >> 16) & 0xFF); // 0xCD
byte b3 = (byte) ((value >> 24) & 0xFF); // 0xAB
Ternary Operator
The ternary condition ? valueIfTrue : valueIfFalse is a compact if-expression:
int score = 73;
// Equivalent to if/else, but produces a value
String grade = score >= 90 ? "A"
: score >= 80 ? "B"
: score >= 70 ? "C"
: score >= 60 ? "D"
: "F";
System.out.println(grade); // C
// Ternary inline in string formatting
int items = 3;
String label = items + " " + (items == 1 ? "item" : "items");
System.out.println(label); // 3 items
// Use for selecting between two values, not for complex logic
int max = (a > b) ? a : b;
instanceof — Type Check
Traditional (Java 1+)
Object obj = "Hello, Java!";
if (obj instanceof String) {
String s = (String) obj; // manual cast required
System.out.println(s.length()); // 12
}
Pattern Matching instanceof (Java 16+)
Object obj = "Hello, Java!";
// Type test + binding in one expression — no manual cast
if (obj instanceof String s) {
System.out.println(s.length()); // 12
}
// Works great in switch (Java 21+)
static String describe(Object obj) {
return switch (obj) {
case Integer i -> "int: " + i;
case Double d -> "double: " + d;
case String s -> "string of length " + s.length();
case int[] a -> "int array of length " + a.length;
case null -> "null";
default -> "other: " + obj.getClass().getSimpleName();
};
}
Operator Precedence
Higher precedence operators bind tighter. When in doubt, use parentheses for clarity.
| Precedence | Operators |
|---|---|
| 1 (highest) | ++ -- (postfix), () [] . |
| 2 | ++ -- (prefix), + - (unary), ~ ! |
| 3 | * / % |
| 4 | + - |
| 5 | << >> >>> |
| 6 | < > <= >= instanceof |
| 7 | == != |
| 8 | & |
| 9 | ^ |
| 10 | | |
| 11 | && |
| 12 | || |
| 13 | ?: (ternary) |
| 14 (lowest) | = += -= *= /= %= etc. |
// Surprises from precedence
System.out.println(2 + 3 * 4); // 14, not 20 — * before +
System.out.println(1 + 2 + "3"); // "33" — left-to-right, int+int+"3"
System.out.println("1" + 2 + 3); // "123" — string concat once string appears
System.out.println(true || false && false); // true — && before ||
// When in doubt, parenthesise
System.out.println((2 + 3) * 4); // 20
Practical Examples
Flag manipulation with bitwise ops
// Permission flags as bit constants
static final int READ = 0b001; // 1
static final int WRITE = 0b010; // 2
static final int EXECUTE = 0b100; // 4
int permissions = READ | WRITE; // 3 — has read and write
// Check permission
boolean canRead = (permissions & READ) != 0; // true
boolean canExecute = (permissions & EXECUTE) != 0; // false
// Grant execute permission
permissions |= EXECUTE; // 7 — now all three
// Revoke write permission
permissions &= ~WRITE; // 5 — READ | EXECUTE
Safe division with ternary
static double safeDivide(double a, double b) {
return b != 0 ? a / b : 0.0;
}
System.out.println(safeDivide(10, 3)); // 3.333...
System.out.println(safeDivide(10, 0)); // 0.0 Frequently Asked Questions
What is the difference between == and .equals() in Java?
== compares references (memory addresses) for objects, and values for primitives. .equals() compares content. For strings, 'hello' == 'hello' may be true due to string interning, but new String('hello') == new String('hello') is false. Always use .equals() to compare object content.
What does the >>> operator do?
>>> is the unsigned right shift operator. Unlike >>, it always fills the leftmost bits with 0, even for negative numbers. This is useful when treating int values as bit patterns regardless of sign.
When should I use the ternary operator?
Use the ternary for simple, single-value assignments where both branches are short expressions: String label = count == 1 ? 'item' : 'items'. Avoid nesting ternaries or using them for side effects — an if/else is clearer in those cases.
What does instanceof do in Java 16+?
The pattern-matching instanceof (Java 16+) tests the type AND binds a variable in one step: if (obj instanceof String s) { ... use s ... }. This eliminates the manual cast that was needed before Java 16.