Skip to content

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, Integer caching, shift wraparound, and division by zero.

Operator families

FamilyOperators
Arithmetic+ - * / % and unary + - ++ --
Relational< > <= >= == !=
Logical&& || ! (short-circuit), & | ^ (boolean, non-short-circuit)
Bitwise& | ^ ~
Shift<< >> >>>
Assignment= and compound += -= *= /= %= &= ...
Ternarycondition ? a : b
Typeinstanceof, 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; assigns 5 to b, then to a.
  • Most binary operators are left-associative: 10 - 4 - 3 is (10 - 4) - 3 = 3.
java
int r = 2 + 3 * 4;     // 14, not 20
boolean t = 1 + 2 > 2; // (1+2) > 2  ->  true

Increment / 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 / 2 is 3, -7 / 2 is -3.
  • Modulus sign follows the dividend: -7 % 3 is -1; 7 % -3 is 1.
  • Integer division/modulus by zero throws ArithmeticException at runtime.
  • Floating-point does not throw: 1.0 / 0 is Infinity, 0.0 / 0 is NaN. NaN is not equal to anything, including itself (NaN == NaN is false).
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 ArithmeticException

Numeric promotion in binary expressions

Before a binary numeric operation, operands are promoted:

  1. If either is double → both double. Else
  2. if either is float → both float. Else
  3. if either is long → both long. Else
  4. both are promoted to int (this is why byte + byte is an int).
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 evaluated

Gotcha

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 = 12

Integer 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 /0 throws, but floating-point /0 gives Infinity/NaN (and NaN != NaN).
  • Binary numeric promotion lifts byte/short/char to int; any long/float/double lifts 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

Lesson Quiz · Operators & Expressions0 / 10
  1. What does this print?

    System.out.println(2 + 3 * 4);
    • A20
    • B14
    • C24
    • DCompile error
  2. What does this print?

    System.out.println(1 + 2 + "X" + 1 + 2);
    • A3X3
    • B3X12
    • C12X12
    • D1 2 X 1 2
  3. Which expressions/statements throw at runtime? (select all that apply) (select all that apply)

    • A1 / 0 (int)
    • B1.0 / 0
    • C0.0 / 0.0
    • D10 % 0 (int)
  4. What is the value of i after: int i = 5; i *= 2.5;

    • ACompile error: cannot assign double to int
    • B12
    • C12.5
    • D13
  5. Given Integer a = 127, b = 127, c = 128, d = 128; which are true? (select all that apply) (select all that apply)

    • Aa == b
    • Bc == d
    • Ca.equals(b)
    • Dc.equals(d)
  6. What does this print?

    System.out.println(1 << 32);
    • A0
    • B1
    • C4294967296
    • DCompile error
  7. What is -7 % 3 in Java?

    • A1
    • B-1
    • C2
    • D-2
  8. Why does if (arr != null && arr.length > 0) avoid a NullPointerException when arr is null?

    • ABecause && evaluates right-to-left
    • BBecause && short-circuits: when the left side is false, the right side is not evaluated
    • CBecause arr.length is null-safe
    • DIt does not; it still throws
  9. What does this print?

    int i = 5;
    int a = i++;
    int b = ++i;
    System.out.println(a + " " + b + " " + i);
    • A5 7 7
    • B6 7 7
    • C5 6 6
    • D6 6 7
  10. What is the type of x + y where byte x = 1, y = 2; ?

    • Abyte
    • Bshort
    • Cint
    • Dlong

Next: the Foundations Mini-Exam on the module overview. Run the matching code in labs/.../m00_foundations/Operators.java.