Skip to content
Java getting started 9 min read

Operators

Operators are the symbols that tell Java how to manipulate variables and values. From adding two numbers to flipping bits in memory, operators are the building blocks of every expression you write.

Categories of Operators

Java groups its operators into several categories. The table below gives you a quick orientation before we dive into each one.

CategorySymbolsPurpose
Arithmetic+ - * / %Math computations
Unary+ - ++ -- !Single-operand operations
Relational== != < > <= >=Compare two values
Logical&& || !Combine boolean conditions
Bitwise& | ^ ~ << >> >>>Bit-level manipulation
Assignment= += -= *=Assign (and optionally compute)
Ternary? :Inline if-else expression
instanceofinstanceofType check at runtime

Arithmetic Operators

These perform the everyday math operations you already know.

public class Arithmetic {
    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   — modulus (remainder)
    }
}

Output:

22
12
85
3
2

Warning: Dividing two int values performs integer division — it drops the decimal part. If you need the fractional result, cast at least one operand to double: (double) a / b3.4.

The % (modulus) operator is extremely useful for tasks like checking if a number is even (n % 2 == 0) or cycling through array indices.

Unary Operators

Unary operators work on a single operand.

public class UnaryDemo {
    public static void main(String[] args) {
        int x = 10;

        System.out.println(+x);   // 10  — unary plus (rarely needed)
        System.out.println(-x);   // -10 — negation
        System.out.println(!true); // false — logical NOT

        // Pre-increment: increment THEN use
        System.out.println(++x);  // 11

        // Post-increment: use THEN increment
        System.out.println(x++);  // 11 (x becomes 12 after this line)
        System.out.println(x);    // 12
    }
}

Output:

10
-10
false
11
11
12

Pre vs Post Increment/Decrement

This trips up nearly every beginner at some point. The rule is simple:

  • Pre (++x / --x): change the value first, then evaluate the expression.
  • Post (x++ / x--): evaluate the expression first, then change the value.
int n = 5;
int a = ++n;  // n becomes 6, a = 6
int b = n++;  // b = 6, then n becomes 7
System.out.println(a + " " + b + " " + n); // 6 6 7

Output:

6 6 7

Relational (Comparison) Operators

Relational operators compare two values and always produce a boolean result (true or false). They are the backbone of if-else and loop conditions.

int x = 10, y = 20;

System.out.println(x == y);  // false — equal to
System.out.println(x != y);  // true  — not equal to
System.out.println(x < y);   // true  — less than
System.out.println(x > y);   // false — greater than
System.out.println(x <= 10); // true  — less than or equal
System.out.println(y >= 20); // true  — greater than or equal

Output:

false
true
true
false
true
true

Warning: Never use == to compare String objects — it checks reference equality (whether two variables point to the same object), not content equality. Use .equals() instead. See String Comparison for the full explanation.

Logical Operators

Logical operators combine boolean expressions. Java provides two styles: short-circuit (&&, ||) and non-short-circuit (&, |).

int age = 25;
boolean hasId = true;

// && — true only if BOTH sides are true
System.out.println(age >= 18 && hasId);   // true

// || — true if AT LEAST ONE side is true
System.out.println(age < 18 || hasId);   // true

// ! — flips a boolean
System.out.println(!hasId);              // false

Output:

true
true
false

Short-Circuit Evaluation

&& and || are short-circuit operators — they stop evaluating as soon as the result is determined.

int[] arr = null;

// Without short-circuit, arr.length would throw NullPointerException
// With &&, if arr == null is true, the right side is never evaluated
if (arr != null && arr.length > 0) {
    System.out.println("Array has elements");
} else {
    System.out.println("Array is null or empty");
}

Output:

Array is null or empty

This pattern — checking for null before accessing a member — is extremely common and relies entirely on short-circuit behavior.

Assignment Operators

The basic assignment operator = stores a value into a variable. Compound assignment operators combine a computation with assignment, making code more concise.

int n = 10;

n += 5;   // same as: n = n + 5  → 15
n -= 3;   // same as: n = n - 3  → 12
n *= 2;   // same as: n = n * 2  → 24
n /= 4;   // same as: n = n / 4  → 6
n %= 4;   // same as: n = n % 4  → 2

System.out.println(n); // 2

Output:

2

Compound operators also work for bitwise operations: &=, |=, ^=, <<=, >>=.

Ternary Operator

The ternary operator ? : is a compact, one-line alternative to if-else. It takes three operands: a condition, a value when true, and a value when false.

int score = 72;
String grade = (score >= 60) ? "Pass" : "Fail";
System.out.println(grade); // Pass

Output:

Pass

Tip: Use the ternary operator for simple, readable assignments. Avoid nesting ternaries inside each other — that quickly becomes hard to read. Reach for a full if-else block instead.

Bitwise Operators

Bitwise operators work directly on the binary (bit) representation of integer values. They are fast and are commonly used in performance-sensitive code, flag manipulation, and low-level programming.

OperatorNameEffect
&AND1 if both bits are 1
|OR1 if either bit is 1
^XOR1 if bits differ
~NOTFlips all bits
<<Left shiftMultiply by 2^n
>>Signed right shiftDivide by 2^n (keeps sign)
>>>Unsigned right shiftDivide by 2^n (fills 0s)
int a = 6;   // binary: 0110
int b = 3;   // binary: 0011

System.out.println(a & b);   // 2  (0010)
System.out.println(a | b);   // 7  (0111)
System.out.println(a ^ b);   // 5  (0101)
System.out.println(~a);      // -7 (flips all 32 bits)
System.out.println(a << 1);  // 12 (1100) — shift left by 1 = ×2
System.out.println(a >> 1);  // 3  (0011) — shift right by 1 = ÷2

Output:

2
7
5
-7
12
3

A very common idiom: use << and >> as fast multiplications and divisions by powers of two, and use & with a mask to test or clear specific bits.

int flags = 0b1010;          // bits 1 and 3 set
boolean bit1Set = (flags & 0b0010) != 0;  // test bit 1
System.out.println(bit1Set); // true

The instanceof Operator

instanceof tests whether an object is an instance of a given class or interface — without throwing a ClassCastException. It always returns a boolean.

Object obj = "Hello";

System.out.println(obj instanceof String);  // true
System.out.println(obj instanceof Integer); // false

Output:

true
false

Since Java 16, the pattern matching form of instanceof (finalized from preview in Java 14) lets you test and cast in one step:

Object obj = "Hello, World!";

if (obj instanceof String s) {
    // s is already a String here — no explicit cast needed
    System.out.println(s.toUpperCase());
}

Output:

HELLO, WORLD!

See Pattern Matching for the full picture, and instanceof Operator for more examples.

Operator Precedence

When an expression contains multiple operators, Java evaluates them in a fixed order called precedence. Higher precedence operators bind tighter (evaluate first).

Precedence (high → low)Operators
Postfixexpr++ expr--
Unary++expr --expr + - ~ !
Multiplicative* / %
Additive+ -
Shift<< >> >>>
Relational< > <= >= instanceof
Equality== !=
Bitwise AND&
Bitwise XOR^
Bitwise OR|
Logical AND&&
Logical OR||
Ternary? :
Assignment= += -=
int result = 2 + 3 * 4;       // 14, not 20 — * before +
int result2 = (2 + 3) * 4;    // 20 — parentheses override
boolean b = 5 > 3 && 10 < 20; // true — > and < before &&

Tip: When in doubt, use parentheses. They cost nothing at runtime and make your intent crystal clear to the next reader (including your future self).

Under the Hood

Integer Arithmetic and Overflow

Java’s int is a 32-bit signed integer. If a computation exceeds Integer.MAX_VALUE (2,147,483,647), it silently wraps around — it does not throw an exception.

int max = Integer.MAX_VALUE;
System.out.println(max + 1); // -2147483648 — wraps to MIN_VALUE

Output:

-2147483648

If overflow is a concern, use long (64-bit), or the Math.addExact() / Math.multiplyExact() methods (Java 8+) that throw ArithmeticException on overflow.

How the JVM Handles Operators

At the bytecode level, Java compiles most operators to dedicated JVM instructions:

  • + on intiadd
  • - on intisub
  • * on intimul
  • / on intidiv
  • <<ishl
  • >>ishr
  • >>>iushr

The JIT compiler (see JIT Compilation) further lowers these to native CPU instructions. Shift and bitwise operations are single CPU cycles, making them the fastest operations available. Addition and multiplication are nearly as fast on modern hardware. Division (/ and %) is typically 20–40× slower than addition because integer division requires a separate CPU circuit.

Promotion Rules

When you mix types in an arithmetic expression, Java promotes the smaller type:

  • byte / short / char operands are always promoted to int before the operation.
  • If one operand is long, float, or double, the other is promoted to match.
byte x = 10;
byte y = 20;
// byte z = x + y;  // COMPILE ERROR — result is int, not byte
int z = x + y;      // correct

This is why you sometimes need an explicit cast when assigning back to a narrower type. See Data Types for the full promotion chain.

  • Variables — the containers operators act upon
  • Data Types — understand how type promotion affects operator results
  • Control Statements — use relational and logical operators to build conditions
  • if-else Statement — put relational operators to work in branching logic
  • JIT Compilation — how the JVM optimizes operator bytecode to native code
  • Pattern Matching — modern use of instanceof with pattern variables (Java 16+)
Last updated June 13, 2026
Was this helpful?