Module 2 · Core Syntax & Types ⏱ 18 min

Ternary and Compound Assignment Operators

By the end of this lesson you will be able to:
  • Evaluate ?: expressions with correct precedence
  • Predict results of +=, -=, *=, /=, and %=
  • Explain when compound assignment includes an implicit cast
  • Choose between a ternary and an if/else for readability

Many decisions in code do exactly one thing: pick a value. If the score is 50 or more, the label is "Pass"; otherwise it is "Fail". Written out as a full if/else, that is four lines and a throwaway variable for what is really a single choice. Java's ternary operator ?: collapses it into one expression: String label = score >= 50 ? "Pass" : "Fail";. It is the only operator in Java that takes three operands, and because it produces a value it can appear anywhere a value can — inside assignments, method arguments, and return statements. Used well, it strips clutter out of your code. Used carelessly, it packs logic so densely that nobody, including you three weeks later, can read it.

flowchart TD
  C["condition"] -->|true| T["value if true"]
  C -->|false| F["value if false"]
  style C fill:#c2410c,color:#fff
The ternary operator chooses a value based on a condition.

A ternary is an expression, not a statement

An if/else is a statement — it directs the flow of the program but produces no value. A ternary is an expression — it resolves to a value you can use immediately. That is why int max = a > b ? a : b; works, while int max = if (a > b) { a } else { b } does not even compile. Because a ternary yields a value, it can be passed straight into a method call — print(status == OK ? "ready" : "waiting") — or returned directly: return n >= 0 ? n : -n;. The real reason the operator exists is not to save lines; it is to let a choice flow into a place where a statement is simply not allowed.

The three parts, and a precedence surprise

The shape is always condition ? valueIfTrue : valueIfFalse. The condition must evaluate to a boolean. Java evaluates the condition first, then evaluates only one of the two branches — the other is skipped, which matters when a branch has side effects. The result type is the common type of the two branches.

The trap is precedence. ?: binds very loosely — looser than arithmetic, looser than +, looser than comparison. So passed ? "Pass" : "Fail" + "!" does not attach "!" to both branches. The + runs first, so Java reads it as passed ? "Pass" : ("Fail" + "!"). When passed is true, you get plain "Pass" with no exclamation mark. The fix is a habit: whenever a ternary shares a line with + or any other operator, wrap the whole ?: in parentheses.

flowchart TD
  E["a ternary with a plus on one branch"] --> G["plus binds tighter than the ternary"]
  G --> P["the plus joins only the false branch"]
  P --> T["condition true gives the first value alone"]
  P --> F["condition false gives the second value plus the extra"]
  style E fill:#c2410c,color:#fff
  style P fill:#1e293b,color:#fff
+ has higher precedence than ?:, so it binds to one branch instead of both.
Main.java — the ternary picking a maximum, a label, and a parity. Real, compiling Java.
public class Main {
    public static void main(String[] args) {
        int a = 8;
        int b = 5;
        int max = a > b ? a : b;
        System.out.println(max);

        int score = 73;
        String grade = score >= 60 ? "Pass" : "Fail";
        System.out.println(grade);

        int n = 7;
        String parity = n % 2 == 0 ? "even" : "odd";
        System.out.println(parity);
    }
}

Compound assignment and its hidden cast

+=, -=, *=, /=, and %= fold an operation into the assignment. x += 5 means x = x + 5. The right side is evaluated completely first, so y *= 2 + 3 becomes y = y * 5, not y = y * 2 + 3.

There is a second, subtler rule: compound assignment silently casts the result back to the variable's type. byte b = 3; b += 200; compiles, because the compiler treats it as b = (byte)(b + 200). The arithmetic 3 + 200 is 203, but a byte only holds the values -128 to 127, so it wraps to -53 — a result you never asked for, delivered with no warning. The long form b = b + 200 would not compile, because b + 200 promotes to int and the compiler refuses to narrow it back without an explicit cast. The compound operator hides that cast from you.

flowchart LR
  S["x += 5"] --> R["compute x + 5"]
  R --> C["cast back to the type of x"]
  C --> Store["store the result in x"]
  SB["byte b then b += 200"] --> CB["b becomes (byte)(b + 200)"]
  CB --> W["203 wraps to -53"]
  style S fill:#c2410c,color:#fff
  style C fill:#b45309,color:#fff
  style W fill:#166534,color:#fff
Compound assignment computes the operation, then silently casts the result back to the variable's type.
Main.java — each compound operator updates total in place. Real, compiling Java.
public class Main {
    public static void main(String[] args) {
        int total = 100;
        total += 50;
        System.out.println(total);
        total -= 30;
        System.out.println(total);
        total *= 2;
        System.out.println(total);
        total /= 4;
        System.out.println(total);
        total %= 10;
        System.out.println(total);
    }
}

When one line stops being clearer

The ternary shines when both branches are simple values and the choice is obvious — picking a maximum, a label, or a default. The moment a branch calls a method, runs a calculation, or chains into another ternary, switch to a full if/else. A construction like a ? b ? c : d : e is technically legal and practically unreadable, and most style guides ban nested ternaries outright.

The same honesty applies to compound assignment. It is the idiomatic way to update an accumulator (total += price), and clearer than writing the long form. But reach for it only when the operation is tiny; a compound line that silently runs three steps has stopped saving anyone any time.

Main.java — ternary and compound assignment. Real, compiling Java.
public class Main {
    public static void main(String[] args) {
        int score = 75;
        String result = score >= 60 ? "Pass" : "Fail";
        System.out.println(result);

        int x = 10;
        x += 5;
        System.out.println(x);

        int y = 7;
        y *= 2 + 3;
        System.out.println(y);

        byte b = 3;
        b += 200;
        System.out.println(b);
    }
}
Exercise

What does this program print? Read each ternary carefully and type the exact output (three lines).

public class Main {
    public static void main(String[] args) {
        int a = 8;
        int b = 5;
        int max = a > b ? a : b;
        System.out.println(max);
        String sign = a - b >= 0 ? "non-negative" : "negative";
        System.out.println(sign);
        int c = 4;
        String parity = c % 2 == 0 ? "even" : "odd";
        System.out.println(parity);
    }
}
Exercise

What does this program print? Read it carefully and type the exact output (four lines).

public class Main {
    public static void main(String[] args) {
        int score = 75;
        String result = score >= 60 ? "Pass" : "Fail";
        System.out.println(result);

        int x = 10;
        x += 5;
        System.out.println(x);

        int y = 7;
        y *= 2 + 3;
        System.out.println(y);

        byte b = 3;
        b += 200;
        System.out.println(b);
    }
}
Exercise

This looks like it should print Pass!, but + binds tighter than ?:. Predict the exact one-line output.

public class Main {
    public static void main(String[] args) {
        boolean passed = true;
        String label = passed ? "Pass" : "Fail" + "!";
        System.out.println(label);
    }
}
Exercise

What is b += 1; equivalent to when b is a byte?

Exercise

A ternary can choose the value a compound operator adds. Orders of 150 or more get free shipping; smaller orders pay the shipping fee. Predict the exact two-line output.

public class Main {
    public static void main(String[] args) {
        int total = 100;
        int shipping = 12;
        total += total >= 150 ? 0 : shipping;
        System.out.println(total);
        total = 200;
        total += total >= 150 ? 0 : shipping;
        System.out.println(total);
    }
}

Recap

  • The ternary cond ? a : b picks a when cond is true, otherwise b; only the chosen branch is evaluated.
  • It is an expression with a value, which is why it can go where an if statement cannot.
  • ?: binds very loosely — parenthesise the whole ternary whenever it shares a line with + or another operator.
  • Compound assignment (+=, -=, *=, /=, %=) evaluates the right side fully first, then casts the result back to the variable's type.
  • That hidden cast lets b += 200 compile on a byte but silently wrap to -53, and it truncates /= on an int.

Next you will put these operators to work inside loops and branches.

Checkpoint quiz

What does int a = 5; a *= 2 + 1; store in a?

What does boolean ok = true; String s = ok ? "Yes" : "No"; store in s?

Go deeper — technical resources