☕ Java
Operators
Operators are the symbols that tell Java what to do with values — add them, compare them, combine them, assign them. Java has a rich set of operators, each with specific behavior, precedence, and type rules. Understanding them deeply prevents subtle bugs and makes your code more expressive.
What Is an Operator?
An operator is a symbol that performs an operation on one or more values (called operands) and produces a result. Java has operators for arithmetic, comparison, logic, bit manipulation, assignment, and more.
Every operator has:
- Arity — how many operands it takes (unary = 1, binary = 2, ternary = 3)
- Precedence — which operator is evaluated first when multiple appear in one expression
- Associativity — whether evaluation goes left-to-right or right-to-left when precedence is equal
- Type rules — what types are valid for its operands and what type it produces
Operator Categories
Java organizes its operators into eight categories:
Java
// 1. Arithmetic — math operations:
+ - * / % ++ --
// 2. Relational — comparisons that produce boolean:
== != > < >= <=
// 3. Logical — boolean logic:
&& || ! ^
// 4. Bitwise — operate on individual bits:
& | ^ ~ << >> >>>
// 5. Assignment — store values:
= += -= *= /= %= &= |= ^= <<= >>= >>>=
// 6. Unary — single operand:
+ - ++ -- ! ~
// 7. Ternary — three-part conditional:
? :
// 8. instanceof — type checking:
instanceofOperator Precedence
When multiple operators appear in one expression, precedence determines evaluation order. Higher precedence operators are evaluated before lower precedence ones. Precedence from highest to lowest:
Java
// Precedence table (highest to lowest):
//
// Level Operator(s) Associativity
// ─────────────────────────────────────────────────────────
// 1 () [] . left → right
// 2 ++ -- (postfix) left → right
// 3 ++ -- (prefix) + - (unary) ~ ! right → left
// 4 * / % left → right
// 5 + - left → right
// 6 << >> >>> left → right
// 7 < > <= >= instanceof left → right
// 8 == != left → right
// 9 & left → right
// 10 ^ left → right
// 11 | left → right
// 12 && left → right
// 13 || left → right
// 14 ? : right → left
// 15 = += -= *= /= etc. right → left
// Examples:
int result = 2 + 3 * 4; // 14 — * before +
int result2 = (2 + 3) * 4; // 20 — () overrides precedence
boolean b = 5 > 3 && 2 < 4; // true — > and < before &&
boolean b2 = true || false && false; // true — && before ||Associativity
When operators have equal precedence, associativity determines evaluation order — left-to-right for most operators, right-to-left for assignment and prefix operators.
Java
// Left-to-right associativity (most operators):
int result = 10 - 3 - 2; // (10 - 3) - 2 = 5, not 10 - (3 - 2) = 9
int div = 24 / 4 / 2; // (24 / 4) / 2 = 3
// Right-to-left associativity (assignment operators):
int a, b, c;
a = b = c = 10; // evaluated as a = (b = (c = 10))
// c gets 10 first, then b gets 10, then a gets 10
// Right-to-left (prefix unary):
int x = 5;
int y = - -x; // -(-5) = 5 — double negation
// Right-to-left (ternary):
int n = 5;
String s = n > 0 ? "positive" : n < 0 ? "negative" : "zero";
// evaluated as: n > 0 ? "positive" : (n < 0 ? "negative" : "zero")Short-Circuit Evaluation
The logical operators && and || use short-circuit evaluation — they stop evaluating as soon as the result is determined. This is both a performance optimization and a safety mechanism.
Java
// && short-circuits on first false:
String name = null;
if (name != null && name.length() > 0) {
// safe — if name is null, name.length() is never called
System.out.println("Name: " + name);
}
// || short-circuits on first true:
if (cache.contains(key) || loadFromDatabase(key)) {
// if cache hit, database is never queried
}
// Non-short-circuit versions — & and | evaluate BOTH sides always:
boolean a = false;
boolean b = someExpensiveMethod(); // called even though a is false
boolean result = a & b; // both evaluated regardless
// When to use & and | (non-short-circuit):
// — when both sides must execute (side effects)
// — in bitwise operations on integers (not booleans)
// Common pattern — null-safe method chaining:
if (user != null
&& user.getAddress() != null
&& user.getAddress().getCity() != null) {
System.out.println(user.getAddress().getCity());
}Type Rules and Promotion in Expressions
Operators follow strict type rules. The result type of an expression depends on the types of its operands — and Java automatically promotes smaller types in mixed expressions.
Java
// Integer arithmetic — result is int minimum:
byte b = 10;
byte b2 = 20;
// byte sum = b + b2; // COMPILE ERROR — result is int
int sum = b + b2; // correct
// Mixed integer types — result is the larger type:
int i = 100;
long l = 200L;
long mixed = i + l; // int promoted to long — result is long
// Mixed with floating point — result is the floating-point type:
int x = 5;
double d = 2.5;
double result = x + d; // int promoted to double — result is double
// Integer division vs floating-point division:
int a = 7, b3 = 2;
int intDiv = a / b3; // 3 — integer division
double fpDiv = a / b3; // 3.0 — still integer division! widened after
double fpDiv2 = (double) a / b3; // 3.5 — correct: cast before dividing
// String + anything = String:
String s = "Value: " + 42; // "Value: 42"
String s2 = "Sum: " + (1 + 2); // "Sum: 3" — parens force int addition first
String s3 = "Sum: " + 1 + 2; // "Sum: 12" — left-to-right, both concatRelated Topics in Java Basics
Variables in Java
A variable is just a named box in memory that holds a value. Java is strict about what goes in each box — you tell it the type upfront. Once you get this, the rest of Java clicks into place.
Data Types in Java
Java needs to know exactly what kind of data it's dealing with before it can store or process it. Integers, decimals, characters, true/false — each has its own type. Knowing which to use (and why) makes your programs efficient and bug-free.
Primitive Data Types
Java has eight primitive data types — the most basic building blocks for storing data. Unlike objects, primitives are stored directly in memory, making them fast and efficient. Understanding each type, its size, range, and when to use it is fundamental to writing correct Java programs.
Non-Primitive Data Types
Non-primitive data types — also called reference types — are everything beyond Java's eight primitives. Strings, arrays, classes, interfaces, enums, and records all fall into this category. They're more powerful than primitives, but they work differently in memory, comparison, and nullability. Understanding the distinction is essential for writing correct Java.