Operators and Expressions

This section documents the current Java release line, with Java 25 LTS as the reference point (no specific patch version is pinned), as published at the Java developer portal, the Java Tutorials, and the Java SE API specification — which are the references these pages are written and verified against.

This content was generated with the assistance of AI and should be verified against the official documentation before being relied on in production.

This section’s bibliography lists the reference material consulted while preparing these pages.

An expression combines values, variables, and method calls with operators to produce a result. This page follows dev.java "Using Operators", the Java Tutorials "Operators" lesson, and JLS chapter 15, "Expressions".

Arithmetic, Unary, and Increment/Decrement

int sum  = 7 + 3;      // 10
int diff = 7 - 3;      // 4
int prod = 7 * 3;      // 21
int quot = 7 / 3;      // 2    -- integer division truncates toward zero
int rem  = 7 % 3;      // 1    -- remainder; its sign follows the dividend:  -7 % 3 == -1
double d = 7.0 / 3;    // 2.3333333333333335  -- one double operand => floating-point division

int neg = -sum;        // unary minus
int pos = +sum;        // unary plus (a no-op, kept for symmetry)

String a = "n = " + 1 + 2;     // "n = 12"  -- + is concatenation once a String is involved
String b = "n = " + (1 + 2);   // "n = 3"

int n = 5;
int post = n++;        // post-increment: post == 5, then n == 6
int pre  = ++n;        // pre-increment:  n == 7, then pre == 7

/ between two integers is integer division (truncates toward zero); % is the remainder, whose result takes the sign of the left operand — not a mathematical modulo. Mixing an integer with a floating-point operand promotes both to floating point (numeric promotion, JLS 5.6). Integer / 0 and % 0 throw ArithmeticException; floating-point division by zero yields Infinity or NaN instead. + is overloaded for String concatenation (details on Strings and Text).

Relational, Logical, and Conditional

boolean lt = 3 < 5;       // <  <=  >  >=  -> boolean
boolean eq = 3 == 3;      // ==  !=
boolean ne = 3 != 4;

// && and || short-circuit: the right operand is skipped once the result is known
String name = null;
if (name != null && name.length() > 0) {     // no NullPointerException: length() is never reached
    // ...
}

boolean ready = cached() || recompute();     // recompute() runs only if cached() is false

boolean not = !ready;                         // logical negation

// & and | also work on boolean, but ALWAYS evaluate both sides -- rarely what you want
boolean both = check(1) & check(2);

// the conditional (ternary) operator:  condition ? whenTrue : whenFalse
int    max   = (lt) ? 5 : 3;
String label = (name == null) ? "anonymous" : name;

== on reference types compares identity, not contents — use equals for objects (see Classes and Objects and Strings and Text). && and || short-circuit and are what you almost always want; the bitwise & / | / ^ accept boolean operands too but never short-circuit. The conditional operator is Java’s only ternary operator, is an expression (not a statement), and its two branches must have compatible types. See JLS 15.25.

Bitwise, Shift, and Assignment

int x = 0b1100;   // 12
int y = 0b1010;   // 10

int and  = x & y;     // 0b1000  (8)
int or   = x | y;     // 0b1110  (14)
int xor  = x ^ y;     // 0b0110  (6)
int notX = ~x;        // -13     -- two's-complement bitwise NOT

int left  = 1 << 4;     // 16    -- left shift, zero-filled
int right = -8 >> 1;    // -4    -- signed (arithmetic) right shift, keeps the sign bit
int uns   = -8 >>> 28;  // 15    -- unsigned right shift, zero-filled; there is no <<<

// assignment is itself an expression that yields the assigned value
int p, q;
p = q = 0;              // q = 0 evaluates to 0, which is then assigned to p

// compound assignment:  v op= e   means   v = (T)(v op e)   -- note the implicit cast
int m = 10;
m += 5;    // 15
m *= 2;    // 30
m >>= 1;   // 15

byte bb = 10;
bb += 300;             // compiles: the implicit (byte) cast wraps the result to 54

Bitwise and shift operators act on int and long (narrower operands promote to int first). >> keeps the sign bit, >>> shifts in zeros, and the shift distance is taken modulo 32 for int or 64 for long. Compound assignment performs a silent narrowing cast, which can hide truncation. See the Java Tutorials "Bitwise and Bit Shift Operators" page.

instanceof, Precedence, and Evaluation Order

Object o = "hello";

// classic form: test, then cast
if (o instanceof String) {
    String s = (String) o;
    System.out.println(s.length());
}

// instanceof type pattern: tests and binds in one step
if (o instanceof String s) {
    System.out.println(s.length());
}

// flow scoping lets the binding be used in the same condition
if (o instanceof String s && !s.isBlank()) {
    System.out.println(s.strip());
}

instanceof tests the runtime type and is always false for null. The pattern form (o instanceof String s) is the entry point to pattern matching — see Pattern Matching.

Java evaluates operands left to right: the left operand (including its side effects) is fully evaluated before the right, and method arguments are evaluated left to right before the call. Only then are operators applied, according to precedence.

int[] arr = new int[3];
int i = 0;
arr[i] = i = 2;        // the index i is read as 0 first; arr[0] is assigned, then i becomes 2
                       // result: arr == {2, 0, 0}, i == 2

int r = first() + second() * 2;   // call first(), then second(), then '*', then '+'

Precedence, from highest to lowest (full grammar in JLS 15):

group            operators                                   associativity
--------------------------------------------------------------------------------
postfix          expr++   expr--                              left to right
unary            ++expr   --expr   +expr   -expr   ~   !      right to left
cast / new       (type)expr   new                             right to left
multiplicative   *   /   %                                    left to right
additive         +   -        (and String +)                  left to right
shift            <<   >>   >>>                                 left to right
relational       <   <=   >   >=   instanceof                  left to right
equality         ==   !=                                       left to right
bitwise AND      &                                             left to right
bitwise XOR      ^                                             left to right
bitwise OR       |                                             left to right
logical AND      &&                                            left to right
logical OR       ||                                            left to right
conditional      ? :                                           right to left
assignment       =  +=  -=  *=  /=  %=  &=  ^=  |=  <<=  >>=  >>>=   right to left

When precedence is not obvious to a reader, add parentheses — they cost nothing and document intent.

See Also