Appearance
Lesson 03 · Operators & Expressions
Objectives
After this lesson you will be able to:
- Use Java's operators and reason about precedence and associativity.
- Predict the result of integer vs. floating-point arithmetic, division, and modulus.
- Apply numeric promotion rules in binary expressions.
- Explain short-circuit logical operators and where side effects do or don't run.
- Avoid the classic traps: compound-assignment casts, string-concat order,
Integercaching, shift wraparound, and division by zero.
Operator families
| Family | Operators |
|---|---|
| Arithmetic | + - * / % and unary + - ++ -- |
| Relational | < > <= >= == != |
| Logical | && || ! (short-circuit), & | ^ (boolean, non-short-circuit) |
| Bitwise | & | ^ ~ |
| Shift | << >> >>> |
| Assignment | = and compound += -= *= /= %= &= ... |
| Ternary | condition ? a : b |
| Type | instanceof, cast (Type) |
Precedence & associativity (the parts that bite)
You don't need the full table memorized, but know the high-impact rules:
- Unary (
++ -- ! ~ (cast)) binds tighter than binary arithmetic. */%bind tighter than+-.- Arithmetic binds tighter than relational, which binds tighter than
&&, then||. - Assignment has the lowest precedence and is right-associative:
a = b = 5;assigns5tob, then toa. - Most binary operators are left-associative:
10 - 4 - 3is(10 - 4) - 3 = 3.
java
int r = 2 + 3 * 4; // 14, not 20
boolean t = 1 + 2 > 2; // (1+2) > 2 -> trueIncrement / decrement: pre vs. post
java
int i = 5;
int a = i++; // a = 5, then i = 6 (post: use, then change)
int j = 5;
int b = ++j; // j = 6, then b = 6 (pre: change, then use)What prints? — evaluation order
java
int i = 1;
int x = i++ + i++ + i;
System.out.println(x + " " + i);Answer: 6 3. Operands are evaluated left to right: the first i++ yields 1 (i→2), the second i++ yields 2 (i→3), and the final i is 3. Sum = 1 + 2 + 3 = 6, with i left at 3.
Integer vs. floating-point arithmetic
- Integer division truncates toward zero:
7 / 2is3,-7 / 2is-3. - Modulus sign follows the dividend:
-7 % 3is-1;7 % -3is1. - Integer division/modulus by zero throws
ArithmeticExceptionat runtime. - Floating-point does not throw:
1.0 / 0isInfinity,0.0 / 0isNaN.NaNis not equal to anything, including itself (NaN == NaNisfalse).
java
System.out.println(7 / 2); // 3
System.out.println(7 % 3); // 1
System.out.println(7.0 / 2); // 3.5 (one double operand promotes the whole expression)
System.out.println(1.0 / 0); // Infinity
// System.out.println(1 / 0); // throws ArithmeticExceptionNumeric promotion in binary expressions
Before a binary numeric operation, operands are promoted:
- If either is
double→ bothdouble. Else - if either is
float→ bothfloat. Else - if either is
long→ bothlong. Else - both are promoted to
int(this is whybyte + byteis anint).
java
byte x = 1, y = 2;
// byte z = x + y; // ✗ x + y is int
int z = x + y; // ✓Logical operators & short-circuiting
&&and||short-circuit: the right side is not evaluated if the result is already determined.&and|(on booleans) always evaluate both sides.
java
int[] arr = null;
if (arr != null && arr.length > 0) { } // safe: arr.length never runs when arr is null
// if (arr != null & arr.length > 0) // would NPE: right side always evaluatedGotcha
Side effects hide here. In if (a() || b()), b() is skipped when a() is true. Exam questions count how many times a method with a print statement runs.
The classic traps
String concatenation is left-to-right
+ is left-associative, and once a String appears, the rest becomes concatenation:
java
System.out.println(1 + 2 + "X"); // "3X" (1+2 first, then concat)
System.out.println("X" + 1 + 2); // "X12" (concat from the left)Compound assignment hides a cast
java
int i = 5;
i *= 2.5; // compiles! equivalent to i = (int)(i * 2.5) = (int)12.5 = 12Integer autoboxing cache (−128…127)
== on boxed Integer compares references. Values in −128…127 are cached, so they share identity; outside that range they don't.
java
Integer a = 127, b = 127;
Integer c = 128, d = 128;
System.out.println(a == b); // true (cached)
System.out.println(c == d); // false (different objects)
System.out.println(c.equals(d)); // true (value comparison)Shift counts wrap
Shift distance is taken mod 32 for int (mod 64 for long):
java
System.out.println(1 << 32); // 1 (32 % 32 == 0, no shift)
System.out.println(1 << 33); // 2>> is signed (sign-extends); >>> is unsigned (zero-fills).
SDET note
== vs .equals() is the #1 source of flaky assertions. For objects (including boxed numbers and String), assert with .equals() / assertEquals, never ==. When an AI assistant writes assert x == y for boxed or string values, that's a bug waiting for a value outside the cache.
Key Takeaways
- Precedence: unary >
* / %>+ -> relational >&&>||> assignment (right-associative). Most binary operators are left-associative. - Integer
/truncates;%sign follows the dividend; integer/0throws, but floating-point/0givesInfinity/NaN(andNaN != NaN). - Binary numeric promotion lifts
byte/short/chartoint; anylong/float/doublelifts the whole expression. &&/||short-circuit;&/|don't.- Traps: string
+is left-to-right; compound assignment casts implicitly;Integer==is cached only for −128…127; shift counts wrap (mod 32 / 64).
Lesson Quiz
What does this print?
System.out.println(2 + 3 * 4);
What does this print?
System.out.println(1 + 2 + "X" + 1 + 2);
Which expressions/statements throw at runtime? (select all that apply) (select all that apply)
What is the value of i after: int i = 5; i *= 2.5;
Given Integer a = 127, b = 127, c = 128, d = 128; which are true? (select all that apply) (select all that apply)
What does this print?
System.out.println(1 << 32);
What is -7 % 3 in Java?
Why does if (arr != null && arr.length > 0) avoid a NullPointerException when arr is null?
What does this print?
int i = 5; int a = i++; int b = ++i; System.out.println(a + " " + b + " " + i);
What is the type of x + y where byte x = 1, y = 2; ?
Next: the Foundations Mini-Exam on the module overview. Run the matching code in labs/.../m00_foundations/Operators.java.