3.2 Unary Operators, Assignment, and Operator Precedence

Key Takeaways

  • Unary operators act upon a single operand; unary plus (+) and minus (-) apply unary numeric promotion (widening byte, short, char to int), while logical complement (!) negates booleans and bitwise inversion (~) inverts bits according to ~x = -(x + 1).
  • Prefix increment and decrement (++x, --x) update the variable in memory before returning the new value to the containing expression, whereas postfix operators (x++, x--) return the original value before updating memory.
  • In expressions with side effects, Java evaluates operands strictly from left to right; the classic self-assignment trap x = x++ restores the original value of x, completely discarding the increment.
  • Compound assignment operators (+=, -=, *=, /=, %=) automatically inject an implicit narrowing cast E1 = (T)((E1) op (E2)), enabling arithmetic on byte, short, and char without compilation errors but risking silent numeric overflow.
  • Operator precedence establishes the syntactic binding of operands, with postfix operators having highest precedence, followed by unary, multiplicative, additive, relational, equality, logical, ternary, and assignment operators.
Last updated: September 2026

3.2 Unary Operators, Assignment, and Operator Precedence

[!NOTE] Exam Focus: The 1Z0-811 examination frequently tests candidate mastery of complex expressions containing prefix and postfix increment/decrement operators, chained assignments, compound assignments on narrow integer types (byte, short), and operator precedence. Candidates must be able to trace operand evaluation from left to right and account for state changes at each execution step.

Java operators are distinguished not only by their mathematical purpose but by their arity (number of operands), precedence (order of binding), and associativity (direction of evaluation among operators of equal rank). Understanding unary operators, assignment expressions, and operator binding rules is critical for accurately predicting program output on the certification exam.


1. Unary Operators: +, -, !, ~

Unary operators operate on a single operand. Java defines four primary non-increment unary operators:

Unary Plus (+) and Unary Minus (-)

  • Unary Plus (+): Explicitly denotes a positive numeric value (rarely needed). Crucially, like binary arithmetic, unary plus applies unary numeric promotion (JLS §5.6.1), automatically promoting any operand narrower than int (byte, short, char) to 32-bit int.
  • Unary Minus (-): Negates the arithmetic sign of its operand, also promoting narrow integer operands to int.
byte b = 15;
// byte negB = -b; // COMPILE ERROR: -b promotes b to int; cannot assign int to byte!
int negB = -b;     // Compiles cleanly: result is -15
byte castNeg = (byte)-b; // Compiles cleanly with explicit narrowing cast

Logical Complement (!)

The logical NOT operator (!) inverts the value of a boolean expression: !true evaluates to false, and !false evaluates to true. It operates strictly on boolean operands; applying ! to numeric types causes an immediate compilation failure.

boolean loggedIn = false;
boolean showLoginPrompt = !loggedIn; // Evaluates to true

Bitwise Inversion / Complement (~)

The bitwise complement operator (~) inverts every bit in an integral value's two's-complement binary representation (converting 0 bits to 1, and 1 bits to 0). The mathematical formula for bitwise inversion on any integer $x$ is:

x=(x+1)\sim x = -(x + 1)

int val = 7;
System.out.println(~val); // Outputs -8  (-(7 + 1))
int zero = 0;
System.out.println(~zero); // Outputs -1 (-(0 + 1))
int neg = -10;
System.out.println(~neg); // Outputs 9   (-(-10 + 1))

Like unary minus, the ~ operator applies unary numeric promotion, promoting byte, short, and char operands to int.


2. Prefix vs. Postfix Increment and Decrement Operators

The increment (++) and decrement (--) operators increase or decrease a variable's value by exactly 1.

x++; // Semantically equivalent to: x = x + 1;
x--; // Semantically equivalent to: x = x - 1;

[!WARNING] Variables Only: Increment and decrement operators can only be applied to variables. Applying them to numeric literals, constants, or parenthesized expressions causes a compile-time error (unexpected type: required variable, found value):

// 10++;      // COMPILE ERROR: 10 is a literal, not a variable
// (x + 1)++; // COMPILE ERROR: (x + 1) is a value expression

Prefix Operators (++x, --x)

In prefix position, the operator precedes the variable. The variable in memory is modified first, and the new, updated value is returned to the containing expression:

int x = 5;
int y = ++x; // Step 1: x increments from 5 to 6 in memory; Step 2: y is assigned the new value 6
System.out.println("x=" + x + ", y=" + y); // Prints: x=6, y=6

Postfix Operators (x++, x--)

In postfix position, the operator follows the variable. The variable's original, current value is captured and returned to the containing expression first; afterward, the variable is modified in memory:

int x = 5;
int y = x++; // Step 1: y is assigned the original value 5; Step 2: x increments from 5 to 6 in memory
System.out.println("x=" + x + ", y=" + y); // Prints: x=6, y=5
OperatorSyntaxNameTiming of Memory MutationValue Returned to Expression
++xPrefixPrefix IncrementIncrements $x$ by 1 before reading valueThe new incremented value
x++PostfixPostfix IncrementIncrements $x$ by 1 after reading valueThe original unincremented value
--xPrefixPrefix DecrementDecrements $x$ by 1 before reading valueThe new decremented value
x--PostfixPostfix DecrementDecrements $x$ by 1 after reading valueThe original undecremented value

3. Dissecting Complex Expressions with Side Effects

On Exam 1Z0-811, you will encounter complex expressions combining prefix and postfix operators across one or more variables. To solve these reliably, always follow this rule from JLS §15.7:

In Java, operands of an operator are strictly evaluated from left to right.

Case Study 1: Mixed Prefix and Postfix on a Single Variable

int a = 5;
int b = a++ + ++a;
System.out.println("a=" + a + ", b=" + b);

Step-by-step trace of a++ + ++a:

  1. Evaluate left operand a++: Postfix captures the current value 5. Variable a is then incremented to 6 in memory.
  2. Evaluate right operand ++a: Prefix increments a from 6 to 7 in memory first, then returns 7.
  3. Perform addition: 5 + 7 = 12.
  4. Assign to b: b = 12. Final state: a = 7, b = 12.

Case Study 2: The Notorious Self-Assignment Trap

int count = 10;
count = count++;
System.out.println(count);

What is printed? Many candidates mistakenly assume 11. The correct output is 10!

Here is the exact bytecode execution sequence:

  1. The right-hand expression count++ is evaluated. Because it is postfix, it yields the current value 10 and schedules count for incrementing.
  2. Variable count is incremented in memory to 11.
  3. The simple assignment operator = executes, storing the yielded value 10 back into variable count.
  4. The 11 in memory is completely overwritten with 10. The final value of count remains 10!

Case Study 3: Multiple Variables in Compound Arithmetic

int x = 3;
int y = 6;
int z = ++x * y-- - x--;
System.out.println("x=" + x + ", y=" + y + ", z=" + z);

Trace:

  1. Multiplication (*) has higher precedence than subtraction (-), but operands evaluate strictly left-to-right:
  2. Left operand of * is ++x: x increments from 3 to 4, yields 4.
  3. Right operand of * is y--: Postfix yields current y value 6, then decrements y to 5.
  4. Perform multiplication: 4 * 6 = 24.
  5. Subtraction operator evaluates its right operand x--: Postfix yields current x value 4, then decrements x to 3.
  6. Perform subtraction: 24 - 4 = 20.
  7. Assign to z: z = 20. Final values: x = 3, y = 5, z = 20.

4. Simple Assignment and Chained Assignment

The simple assignment operator (=) assigns the value of the right-hand expression to the variable named on the left.

Assignment is an Expression

In Java, an assignment is not merely a statement—it is an expression that returns the value being assigned. Because assignment associates from right to left, you can chain assignments:

int a, b, c;
a = b = c = 100; // Evaluates right-to-left: (a = (b = (c = 100)))
// All three variables receive 100

The Boolean Assignment Trap in Conditions

Because assignment returns a value, writing an assignment inside a conditional statement is syntactically legal if the variable is boolean:

boolean isClosed = false;
if (isClosed = true) { // Assigns true to isClosed, and the expression evaluates to true!
    System.out.println("Store is closed"); // ALWAYS EXECUTES!
}

If the variable is numeric, such as if (x = 5), the code fails compilation because the expression evaluates to integer 5, which cannot be converted to boolean.


5. Compound Assignment Operators & The Implicit Cast Rule

Java provides eleven compound assignment operators: +=, -=, *=, /=, %=, &=, |=, ^=, <<=, >>=, and >>>=.

A compound assignment operator combines an arithmetic or bitwise operation with assignment:

x += 5; // Conceptually related to: x = x + 5;

The Implicit Narrowing Cast Rule (JLS §15.26.2)

There is a critical architectural difference between simple assignment with addition and compound assignment. The Java Language Specification formally defines that a compound assignment of the form:

E1 op=E2E_1 \text{ op}= E_2

is equivalent to:

E1=(T)((E1) op (E2))E_1 = (T)((E_1) \text{ op } (E_2))

where $T$ is the declared data type of variable $E_1$, with $E_1$ evaluated only once.

This means compound assignment operators automatically insert an implicit narrowing cast back to the type of the left-hand variable!

short s = 20;
// s = s + 5; // COMPILE ERROR: s + 5 promotes to int; cannot assign int to short!
s += 5;       // COMPILES CLEANLY: Compiler injects (short)(s + 5)

byte b = 50;
// b = b * 2; // COMPILE ERROR: b * 2 produces int!
b *= 2;       // COMPILES CLEANLY: Compiler injects (byte)(b * 2)

The Silent Numeric Overflow Danger

Because compound assignment operators inject an explicit cast without compiler warning, numeric overflow can occur silently at runtime:

byte maxByte = 127;
maxByte += 1; // Evaluates to (byte)(128) -> wraps around to -128 in two's complement!
System.out.println(maxByte); // Prints: -128 (no error, no exception)

6. Comprehensive Operator Precedence & Associativity Hierarchy

When multiple operators appear in a single expression without parentheses, Java's operator precedence determines how operands bind to operators. When two operators share the same precedence level, associativity dictates whether evaluation groups from left to right or from right to left.

Precedence LevelOperator CategorySpecific OperatorsAssociativity
1 (Highest)Postfixexpr++, expr--Left-to-Right
2Unary Prefix++expr, --expr, +expr, -expr, ~, !Right-to-Left
3Cast / Creation(type), newRight-to-Left
4Multiplicative*, /, %Left-to-Right
5Additive+, -Left-to-Right
6Shift<<, >>, >>>Left-to-Right
7Relational<, <=, >, >=, instanceofLeft-to-Right
8Equality==, !=Left-to-Right
9Bitwise AND&Left-to-Right
10Bitwise XOR^Left-to-Right
11Bitwise OR&#124;Left-to-Right
12Conditional AND&&Left-to-Right
13Conditional OR&#124;&#124;Left-to-Right
14Ternary Conditional? :Right-to-Left
15 (Lowest)Assignment=, +=, -=, *=, /=, %=, etc.Right-to-Left

Using Parentheses to Override Precedence

Parentheses () possess the highest binding power and can be used to explicitly dictate evaluation order and eliminate ambiguity:

int result1 = 5 + 3 * 2;     // 5 + 6 = 11 (* takes precedence over +)
int result2 = (5 + 3) * 2;   // 8 * 2 = 16 (parentheses force addition first)
Loading diagram...
Prefix vs. Postfix Evaluation Lifecycle and State Changes
Test Your Knowledge

Consider the following Java code declarations and assignment statements:

short val1 = 15;
short val2 = 30;
// Statement 1:
val1 = val1 + val2;
// Statement 2:
val1 += val2;
Which of the following statements correctly describes how the compiler handles Statement 1 and Statement 2?

A
B
C
D
Test Your Knowledge

What is the console output when the following Java code executes?

int x = 4;
int y = ++x * 2 + x++ - --x;
System.out.println("x=" + x + ", y=" + y);

A
B
C
D
Test Your Knowledge

What is printed to the console when the following statements are executed?

int a = 8;
int b = ~a;
int c = a - b;
System.out.println(b + " " + c);

A
B
C
D