☕ Java
Unary Operators
Unary operators take a single operand. Java has five: unary plus, unary minus, increment, decrement, and logical NOT. The increment and decrement operators have prefix and postfix forms that behave differently — a distinction that trips up developers at every level.
The Five Unary Operators
Java has five unary operators — each takes exactly one operand:
Java
+ // unary plus — explicitly marks a value as positive (rarely used)
- // unary minus — negates a value
++ // increment — adds 1 (prefix and postfix forms)
-- // decrement — subtracts 1 (prefix and postfix forms)
! // logical NOT — inverts a boolean+ and - Unary Operators
Unary minus negates a numeric value. Unary plus is syntactically valid but rarely used — it doesn't change the value, but it does trigger type promotion to int for byte and short.
Java
// Unary minus — negates:
int a = 5;
int b = -a; // -5
System.out.println(-10); // -10
System.out.println(-(-5)); // 5 — double negation
// Negating variables:
int temperature = 30;
int belowZero = -temperature; // -30
double d = 3.14;
double neg = -d; // -3.14
// Unary minus on expressions:
int x = 3, y = 4;
int result = -(x + y); // -(7) = -7
// Unary plus — promotes byte/short to int, otherwise no effect:
byte b = 42;
// byte promoted = +b; // COMPILE ERROR — +b is int, not byte
int promoted = +b; // 42 — type promoted to int
int i = 5;
int same = +i; // 5 — no change for int
// Practical use of unary minus:
int[] temps = {-10, 5, -3, 8, -15};
for (int t : temps) {
if (t < 0) System.out.println("Below zero: " + (-t) + " degrees cold");
}++ and -- Prefix vs Postfix
Increment and decrement operators exist in two forms. The position of the operator — before or after the operand — determines when the update happens relative to the value being used.
Java
// Prefix (++x) — increment FIRST, then use the new value:
int a = 5;
int b = ++a;
System.out.println(a); // 6 — incremented
System.out.println(b); // 6 — received the incremented value
// Postfix (x++) — use the current value FIRST, then increment:
int x = 5;
int y = x++;
System.out.println(x); // 6 — incremented
System.out.println(y); // 5 — received the ORIGINAL value
// Same with decrement:
int m = 10;
int n = --m; // prefix: m=9, n=9
System.out.println(m + " " + n); // 9 9
int p = 10;
int q = p--; // postfix: q=10, then p=9
System.out.println(p + " " + q); // 9 10
// In isolation — no difference:
int count = 0;
count++; // same result as ++count when not in an expression
++count; // both just add 1
// In expressions — significant difference:
int i = 3;
System.out.println(i++ * 2); // 6 — uses 3, then i becomes 4
System.out.println(++i * 2); // 10 — i becomes 5 first, then 5*2
// Classic postfix trap:
int val = 5;
val = val++; // val is STILL 5!
// Sequence: temp=val(5), val=val+1(6), val=temp(5) — postfix returns original
System.out.println(val); // 5 — not 6!
// The correct way to increment and keep:
val = val + 1; // or: val++; (as standalone statement, not expression)++ and -- in Loops
Increment and decrement are most commonly seen in for loops. In the loop update clause, prefix and postfix produce identical results — there's no expression context, so the timing difference doesn't matter.
Java
// In for loop update — i++ and ++i are identical in effect:
for (int i = 0; i < 5; i++) {
System.out.print(i + " "); // 0 1 2 3 4
}
for (int i = 0; i < 5; ++i) {
System.out.print(i + " "); // 0 1 2 3 4 — identical output
}
// Counting down with --:
for (int i = 5; i > 0; i--) {
System.out.print(i + " "); // 5 4 3 2 1
}
// While loop:
int n = 10;
while (n-- > 0) {
System.out.print(n + " "); // 9 8 7 6 5 4 3 2 1 0
}
// Note: n-- uses n (10) for the > 0 check, then decrements
// Loop runs while n was > 0, but prints already-decremented n
// Contrast with prefix:
n = 10;
while (--n > 0) {
System.out.print(n + " "); // 9 8 7 6 5 4 3 2 1
}
// --n decrements first (10→9), then checks 9 > 0
// Stops when --n produces 0 (which is not > 0)! — Logical NOT
! inverts a boolean value. It's unary, prefix-only, and has high precedence — be careful with complex expressions.
Java
// Basic NOT:
System.out.println(!true); // false
System.out.println(!false); // true
// NOT with boolean variables:
boolean isLoggedIn = false;
if (!isLoggedIn) {
System.out.println("Please log in");
}
// NOT with comparisons — parentheses control precedence:
int x = 5;
System.out.println(!(x > 3)); // false — NOT(true) = false
System.out.println(!x > 3); // COMPILE ERROR — !x is invalid (!int)
// De Morgan's law — simplify negated conditions:
// !(A && B) == (!A || !B)
// !(A || B) == (!A && !B)
// Apply De Morgan to simplify:
if (!(age < 18 || score < 50)) { } // hard to read
if (age >= 18 && score >= 50) { } // cleaner equivalent
if (!(isAdmin && isVerified)) { } // readable but complex
if (!isAdmin || !isVerified) { } // De Morgan applied
// NOT with method return values:
List<String> list = List.of("a", "b", "c");
if (!list.isEmpty()) {
System.out.println("List has " + list.size() + " items");
}
if (!str.contains("@")) {
throw new IllegalArgumentException("Not a valid email");
}~ — Bitwise NOT (Complement)
~ is the bitwise complement operator — it inverts every bit of an integer. It's sometimes categorized with unary operators because it takes one operand.
Java
// ~ inverts all bits — result is -(n+1):
System.out.println(~0); // -1
System.out.println(~1); // -2
System.out.println(~5); // -6
System.out.println(~(-1)); // 0
// Formula: ~n == -(n + 1)
// Practical uses:
// 1. Check indexOf results — indexOf returns -1 if not found:
String text = "Hello World";
if (~text.indexOf("World") != 0) { // ~(-1) == 0, so != 0 means found
System.out.println("Found");
}
// More readable alternative:
if (text.indexOf("World") != -1) {
System.out.println("Found");
}
// Or best:
if (text.contains("World")) {
System.out.println("Found");
}
// 2. Creating inverse bitmasks:
int mask = 0x0F; // 0000 1111
int inverse = ~mask; // 1111 0000
// 3. Clearing bits with ~:
int flags = 0xFF;
int WRITE_FLAG = 0b00000010;
flags &= ~WRITE_FLAG; // clear the write bitRelated Topics in Java Basics
Logical Operators
Logical operators combine boolean expressions into more complex conditions. Java has six of them — short-circuit and non-short-circuit variants of AND, OR, and XOR, plus logical NOT. Understanding short-circuit evaluation is essential for writing both safe and efficient conditions.
Bitwise Operators
Bitwise operators work directly on the binary representation of integers — manipulating individual bits. They're used in low-level programming, performance-critical code, flags, masks, and cryptography. Understanding them requires thinking in binary, but the patterns they enable are concise and extremely fast.
Assignment Operators
Assignment operators store values into variables. Java has one basic assignment operator and eleven compound assignment operators that combine an operation with assignment. They're concise, but have specific type behavior — especially the implicit cast in compound assignments — that every Java developer needs to understand.
Ternary Operator
The ternary operator is Java's only three-operand operator. It's a compact conditional expression that returns one of two values based on a boolean condition. Used correctly, it makes code more concise. Overused or nested, it makes code unreadable.