1.2 Operators, Precedence, and Type Casting
Key Takeaways
- Java expressions evaluate operands strictly from left to right before operator precedence determines how operations are combined.
- Binary numeric promotion automatically widens any byte, short, or char operands to int before performing arithmetic, bitwise, or shift operations.
- Short-circuit logical operators (&& and ||) skip evaluation of the right-hand operand whenever the left-hand operand decisively establishes the boolean outcome.
- Compound assignment operators (e.g., +=, *=, >>>=) automatically inject an implicit narrowing cast back to the target variable's type, masking potential precision loss.
Operators, Precedence, and Type Casting
Operators form the computational engine of Java programming. On the 1Z0-830 exam, questions frequently test edge cases surrounding evaluation order, numeric promotion of smaller types, short-circuit side effects, shift mechanics, and compound assignment implicit casts.
1. Operator Precedence and Associativity Table
Operators are listed from highest precedence (evaluated first) to lowest precedence (evaluated last):
| Precedence Tier | Operators | Associativity | Description |
|---|---|---|---|
| 1. Postfix | expr++ expr-- | Left-to-right | Post-increment and post-decrement |
| 2. Unary | ++expr --expr +expr -expr ~ ! | Right-to-left | Pre-inc/dec, unary signs, bitwise complement, logical NOT |
| 3. Cast & Creation | (type) new | Right-to-left | Type casting and object instantiation |
| 4. Multiplicative | * / % | Left-to-right | Multiplication, division, remainder (modulo) |
| 5. Additive | + - | Left-to-right | Addition, subtraction, string concatenation |
| 6. Shift | << >> >>> | Left-to-right | Signed left, signed right, unsigned (zero-fill) right shift |
| 7. Relational | < > <= >= instanceof | Left-to-right | Comparison and type inspection |
| 8. Equality | == != | Left-to-right | Primitive value and reference address equality |
| 9. Bitwise AND | & | Left-to-right | Integer bitwise AND / Boolean non-short-circuit AND |
| 10. Bitwise XOR | ^ | Left-to-right | Integer bitwise XOR / Boolean logical XOR |
| 11. Bitwise OR | | | Left-to-right | Integer bitwise OR / Boolean non-short-circuit OR |
| 12. Logical AND | && | Left-to-right | Short-circuit conditional AND |
| 13. Logical OR | || | Left-to-right | Short-circuit conditional OR |
| 14. Ternary | ? : | Right-to-left | Conditional ternary operator |
| 15. Assignment | = += -= *= /= %= <<= >>= >>>= &= ^= |= | Right-to-left | Simple and compound assignments |
[!IMPORTANT] Left-to-Right Operand Evaluation Rule: Regardless of operator precedence, Java guarantees that all operand sub-expressions are evaluated strictly from left to right before the operator is applied.
2. Unary and Increment / Decrement Semantics
- Postfix (
x++,x--): Returns the original value ofxfor use in the surrounding expression, and then increments or decrementsxin memory. - Prefix (
++x,--x): Increments or decrementsxin memory first, and then returns the newly modified value.
int a = 5;
int b = a++; // b = 5, a = 6
int c = ++a; // a = 7, c = 7
int x = 3;
x = x++; // Step 1: Evaluates x (3). Step 2: Increments x to 4. Step 3: Assigns evaluated value (3) back to x.
System.out.println(x); // Prints 3!
int y = 5;
int result = y++ * 3 + ++y * 2 + y--;
// Step 1: y++ returns 5 (y becomes 6)
// Step 2: ++y returns 7 (y becomes 7)
// Step 3: y-- returns 7 (y becomes 6)
// Multiplications: (5 * 3) = 15, (7 * 2) = 14
// Additions: 15 + 14 + 7 = 36
// result = 36, y = 6
Bitwise Complement (~)
The ~ operator inverts every bit of an integer type (0 becomes 1, 1 becomes 0). Under two's complement arithmetic:
~0equals-1~5equals-6~(-10)equals9
3. Binary Numeric Promotion Rules
When evaluating binary arithmetic or bitwise operators (+, -, *, /, %, &, |, ^), the compiler automatically applies binary numeric promotion according to these strict rules in order:
- If any operand is
double, the other is promoted todouble. - Otherwise, if any operand is
float, the other is promoted tofloat. - Otherwise, if any operand is
long, the other is promoted tolong. - Otherwise, BOTH operands are promoted to
int, even if both operands arebyte,short, orchar.
byte b1 = 10;
byte b2 = 20;
// byte b3 = b1 + b2; // COMPILE ERROR: b1 + b2 produces an int!
byte b3 = (byte)(b1 + b2); // Legal: Explicit cast back to byte
short s1 = 100;
char c1 = 'A'; // Unicode 65
int sum = s1 + c1; // Both promoted to int; sum = 165
Constant Value Narrowing
The compiler allows assigning a compile-time constant int expression to byte, short, or char without an explicit cast only if the value fits within the target type's range:
byte b = 127; // Legal: 127 fits in byte (-128 to 127)
// byte b2 = 128; // COMPILE ERROR: 128 exceeds byte capacity
final int x = 50;
byte b4 = x; // Legal: x is a compile-time constant and fits in byte
int y = 50;
// byte b5 = y; // COMPILE ERROR: y is not final; requires explicit cast (byte)y
4. Division, Remainder, and Floating-Point Edge Cases
- Integer Division (
/): Truncates towards zero.7 / 2evaluates to3;-7 / 2evaluates to-3. - Division by Zero (
int): Dividing an integer by literal0or integer variable0throwsjava.lang.ArithmeticException: / by zeroat runtime. - Floating-Point Division by Zero: Does not throw an exception. Follows IEEE 754 standards:
10.0 / 0.0$\rightarrow$Double.POSITIVE_INFINITY-10.0 / 0.0$\rightarrow$Double.NEGATIVE_INFINITY0.0 / 0.0$\rightarrow$Double.NaN(Not a Number)
- Remainder Operator (
%): The sign of the result is determined strictly by the sign of the left-hand operand (dividend):7 % 3=17 % -3=1-7 % 3=-1-7 % -3=-1
5. Shift Operators and Bit Masking
Java provides three binary shift operators:
<<(Signed Left Shift): Shifts bits left, filling empty lower bits with0. Equivalent to multiplying by $2^n$ (ignoring overflow).>>(Signed Right Shift): Shifts bits right, preserving the sign bit (copies the highest sign bit into vacated upper positions). Known as arithmetic right shift.>>>(Unsigned Right Shift): Shifts bits right, always filling vacated upper positions with0regardless of the original sign. Known as logical right shift.
Shift Distance Bit Masking
The shift distance is masked by the compiler:
- For
intoperands: only the lowest 5 bits of the distance are used (distance & 0x1F, meaning modulo 32). Shifting anintby 32 positions results in a shift of0(x << 32 == x << 0). - For
longoperands: only the lowest 6 bits of the distance are used (distance & 0x3F, meaning modulo 64). Shifting alongby 64 positions results in a shift of0.
int val = -8;
System.out.println(val >> 1); // Prints -4 (sign bit 1 preserved)
System.out.println(val >>> 1); // Prints 2147483644 (high bit filled with 0)
int n = 1;
System.out.println(n << 32); // Prints 1 (shift distance 32 % 32 = 0)
System.out.println(n << 33); // Prints 2 (shift distance 33 % 32 = 1)
6. Short-Circuit vs. Bitwise Logical Operators
| Operator | Type | Behavior |
|---|---|---|
&& | Conditional AND | Short-circuit: If left operand is false, right operand is never evaluated. |
|| | Conditional OR | Short-circuit: If left operand is true, right operand is never evaluated. |
& | Logical AND | Non-short-circuit: Both left and right operands are always evaluated. |
| | Logical OR | Non-short-circuit: Both left and right operands are always evaluated. |
^ | Logical XOR | Non-short-circuit: Evaluates both; returns true if operands have different truth values. |
int count = 0;
boolean flag = (5 > 10) && (++count > 0);
// Left is false -> right-hand side (++count > 0) is SKIPPED entirely
System.out.println(count); // Prints 0
boolean flag2 = (5 > 10) & (++count > 0);
// Non-short-circuit & evaluates BOTH sides
System.out.println(count); // Prints 1
7. Compound Assignment Operators and Implicit Narrowing
Compound assignment expressions (E1 op= E2) are functionally equivalent to:
where $T$ is the declared type of $E1$, except that $E1$ is evaluated only once.
short s = 5;
// s = s + 10; // COMPILE ERROR: s + 10 promotes to int; cannot assign int to short
s += 10; // Legal! Equivalent to: s = (short)(s + 10);
byte b = 100;
b += 30; // b becomes (byte)(130) = -126 (Overflow occurs silently without error)
long large = 500L;
int target = 10;
target *= large; // Legal! Equivalent to: target = (int)(target * large);
Examine the following code snippet: short a = 10; short b = 20; a = a + b; short c = 30; c += b; Which statement correctly describes what happens when attempting to compile and execute this code?
What is the output of the following Java program? public class PrecedenceEvaluation { public static void main(String[] args) { int i = 2; int j = i++ * 3 + ++i * 2 + i--; System.out.println("i=" + i + ", j=" + j); } }
What is the printed output of the following code snippet? int x = 5; int y = 10; boolean check = (x++ > 5) && (++y > 10); boolean check2 = (++x > 6) | (y++ > 10); System.out.println("x=" + x + ", y=" + y);
Consider the following bit-shift expressions in Java: int a = -16 >> 2; int b = -16 >>> 2; int c = 1 << 35; Which statement accurately describes the resulting values of a, b, and c?