The Java ternary operator with autoboxing can produce surprising results when type promotion rules apply.
A quick puzzle
Take a look at this code:
public class Main {
public static void main(String[] args) {
Object o = true ? Integer.valueOf(1) : Double.valueOf(2.0);
System.out.println(o.getClass().getName() + " -> " + o);
}
}
Question:
What will this program print?
Did you expect:
java.lang.Integer -> 1
…but the actual output is:
java.lang.Double -> 1.0
Surprised? Let’s unpack why.
TL;DR
- In a ternary expression, if the two branches are boxed numeric types (e.g.
IntegerandDouble), the compiler may unbox, promote, and rebox them. - In this example,
Integergets unboxed toint, promoted todouble(sincedoublewins overintin numeric promotion), and then reboxed into aDouble. - Result: you always get a
Double, even if the chosen branch was originally anInteger.
The rules (JLS references)
The magic comes from the Java Language Specification:
- Conditional Operator (§15.25)https://docs.oracle.com/javase/specs/jls/se8/html/jls-15.html#jls-15.25
- The result type of
a ? b : cdepends on the types ofbandc. - If both are numeric, Java may apply unboxing and numeric promotion rules to determine the common type.
- The result type of
- Boxing & Unboxing (§5.1.7, §5.1.8)
Integerunboxes toint,Doubleunboxes todouble.
- Numeric Promotions (§5.6.2)
- When combining
intanddouble, theintis promoted todouble.
- When combining
- Boxing (§5.1.7)
- The resulting
doubleis boxed into aDouble.
- The resulting

More Examples
Example 1: Integer vs Double
Object o = false ? Integer.valueOf(1) : Double.valueOf(2.0);
System.out.println(o.getClass().getName() + " -> " + o);
Output:
java.lang.Double -> 2.0
Even when the Integer branch is never taken, the type is resolved at compile time, so the whole expression is a Double.
Example 2: Casting to a common supertype
Number n = true ? (Number) Integer.valueOf(1) : Double.valueOf(2.0);
System.out.println(n.getClass().getName() + " -> " + n);
Output:
java.lang.Integer -> 1
Why? Because both branches are now typed as Number. No unboxing/promotion is needed, so the chosen branch’s type is preserved.
Example 3: Primitives + Wrappers
Object o = true ? 1 : Double.valueOf(2.0);
System.out.println(o.getClass().getName() + " -> " + o);
Output:
java.lang.Double -> 1.0
Here, 1 is a primitive int. The compiler promotes it to double, then boxes into Double.
Example 4: Float and Integer
Object o = true ? Float.valueOf(1.0f) : Integer.valueOf(42);
System.out.println(o.getClass().getName() + " -> " + o);
Output:
java.lang.Float -> 1.0
Again, both are unboxed → numeric promotion (int → float) → reboxed to Float.
Key Takeaways
- Ternary + Boxed Numerics = Hidden Conversions
- If branches are
Integer,Double,Float, etc., Java often unboxes, promotes, and reboxes.
- If branches are
- If you want to preserve wrapper types:
- Cast both branches to a common supertype (
Number,Object) - Or avoid mixing different boxed numerics.
- Cast both branches to a common supertype (
- Readability matters.
- If the type coercion isn’t obvious to future readers, use an explicit
if/elsefor clarity.
- If the type coercion isn’t obvious to future readers, use an explicit
This flow shows the decision process: same wrapper → keep it, different wrappers → unbox, promote, then box again.

Closing
The ternary operator is elegant, but in Java, it can hide subtle coercions when autoboxing and numeric promotion get involved. Knowing the JLS rules behind it helps avoid surprises — and helps you explain to your teammates why Integer.valueOf(1) suddenly became a Double.
Java Ternary Operator, Autoboxing & Type Promotion — A Subtle Trap
Related posts
Feed
- India
- World
- Live
- Cricket News
To find out more, including how to control cookies, see here Cookie Policy




