Ternary Operator in Java – How It Works and When to Use It
The ternary operator ?: (the Java Language Specification calls it the conditional operator) is the only operator in Java that takes three operands — hence the name «ternary». It picks one of two values depending on a condition and is often used as a compact alternative to a short if-else statement. The key difference: the ternary operator is an expression — it produces a value that you can assign to a variable, pass to a method, or return from a method.
Ternary Operator Syntax
General form of the ternary operator:
condition ? expression1 : expression2 The condition is any expression that evaluates to a boolean value — for example, a comparison or a combination of logical operators.
If the condition is true, expression1 is evaluated and its value becomes the result of the whole expression; otherwise expression2 is evaluated. Note that only one of the two branches is ever evaluated — the other is skipped entirely.
Expression1 and expression2 must produce values of the same (or compatible) type, and that type cannot be void.
Important
The ternary operator is an expression, not a control-flow statement. It must produce a value, so a standalone line like condition ? doThis() : doThat(); will not compile if the methods return void. When you just need to perform one of two actions, use if-else.
Usage Example
A classic example is computing the absolute value of a number: if i is negative, take -i, otherwise take i itself:
public class TernaryOperationExample1 {
public static void main(String[] args) {
int i, k;
i = -10;
k = i < 0 ? -i : i; // absolute value of i
System.out.print("Absolute value of ");
System.out.println(i + " is " + k); // Absolute value of -10 is 10
}
} The same logic written with if-else would take four lines. Two more typical uses — as a method argument and in a return statement:
int a = 7, b = 12;
System.out.println(a > b ? "a is greater" : "b is greater or equal"); // as a method argument
int max(int x, int y) {
return x > y ? x : y; // in a return statement
} Ternary Operator vs if-else: Which to Choose
The ternary operator and if-else are not fully interchangeable — each has its own territory:
| Situation | What to use | Why |
|---|---|---|
Choosing one of two values in an assignment or a return | Ternary operator | Shorter and reads as a single expression: k = i < 0 ? -i : i; |
| Performing actions (printing, changing state) rather than choosing a value | if-else | A ternary must produce a value and cannot stand alone with void branches |
| Multiple statements per branch | if-else | Each branch of a ternary is exactly one expression |
| Three or more alternatives | if-else if or a switch expression | Chains of nested ternaries are hard to read |
Nested Ternary Operators
A branch of a ternary operator can itself be another ternary operator. The operator is right-associative: the expression a ? b : c ? d : e is evaluated as a ? b : (c ? d : e), so a chain without parentheses reads top to bottom, just like an if-else if ladder:
public class NestedTernaryExample {
public static void main(String[] args) {
int score = 74;
String grade = score >= 90 ? "A"
: score >= 70 ? "B"
: score >= 50 ? "C"
: "F";
System.out.println(grade); // B
}
} One level of nesting formatted as a «ladder» like this is still acceptable, but deeper or irregularly arranged nested ternaries quickly turn into a puzzle. Since Java 14, a switch expression — which, like the ternary operator, produces a value — is usually a better fit for choosing among several options:
String size = switch (code) {
case 1 -> "S";
case 2 -> "M";
default -> "L";
}; Common Pitfalls
Two subtleties of the ternary operator show up in interview questions again and again.
1. Numeric promotion. If the branches have different numeric types, the result is converted to their common type before the branch is chosen:
Object result = true ? 1 : 2.0;
System.out.println(result); // 1.0, not 1! Even though the condition is true and the 1 branch is selected, the type of the whole expression is double (the common type of int and double), so 1 is promoted to 1.0.
2. NullPointerException from auto-unboxing. If one branch has a wrapper type (Integer) and the other a primitive (int), the type of the expression is the primitive, and the wrapper is automatically unboxed. If it holds null, the program crashes:
Integer count = null;
boolean flag = true;
int r = flag ? count : 0; // NullPointerException: count is unboxed to int Important
The result type of a ternary operator is determined by both branches at compile time, not by the branch that actually runs. Mixing int and double yields double; mixing Integer and int yields int with auto-unboxing — and a risk of NullPointerException. Keep both branches the same type.
Style and Readability
A few practical guidelines:
- Use the ternary operator for short choices between two values; as soon as the expression stops fitting on one line and being readable at a glance, switch to
if-else. - Avoid side effects in the branches (calls to methods that change state): a reader expects a ternary to be a simple choice of a value.
- Do not nest ternary operators deeper than one level; for chains of conditions use
if-else ifor a switch expression. - When in doubt about operator precedence, wrap the condition in parentheses:
(a > b) ? a : b— it changes nothing for the compiler but helps the reader.
Frequently Asked Questions
What is the difference between the ternary operator and if-else in Java?
The ternary operator is an expression: it produces a value that you can assign to a variable, pass to a method, or return with return. The if-else statement is a control-flow construct: it performs actions but does not produce a value itself. Performance-wise they are equivalent — the choice is about readability, not speed.
Can ternary operators be nested in Java?
Yes, a branch of a ternary operator can be another ternary operator. The operator is right-associative: a ? b : c ? d : e means a ? b : (c ? d : e) and reads like an if-else if chain. Deep nesting hurts readability, though — for three or more alternatives prefer if-else if or a switch expression (Java 14+).
Why does true ? 1 : 2.0 return 1.0 instead of 1?
The compiler determines the result type of a ternary from the types of both branches, not from the branch that actually runs. The common type of int and double is double, so the value 1 is promoted to 1.0. To avoid surprises, keep both branches the same type.
Can the ternary operator throw a NullPointerException?
Yes. If one branch has a wrapper type such as Integer and the other a primitive int, the type of the whole expression is the primitive, and the wrapper value is automatically unboxed. If it holds null, the unboxing throws a NullPointerException, even when the condition looks harmless. The fix is to make both branches the same type.
Comments