The short answer to your question is that the printed value is based on a type that evaluates to a conditional expression.
So your question comes down to why the type of conditional expression is different from
char y = 'y'; int i = 0; System.out.print(false ? i : y);
and
char y = 'y'; System.out.print(false ? 0 : y);
To answer this question, we need to take a look at the §15.25 section of the Java language specification .
There are three types of conditional expression in Java:
- Boolean conditional expressions
- Numeric Conditional Expressions
- Conditional conditional expressions
Since both int and char converted to a numeric type, the expression is an example of a numeric conditional expression in accordance with this rule:
If both the second and third expressions of the operand are numerical expressions, the conditional expression is a numerical conditional expression.
In order to classify a conditional expression, the following expressions are numerical expressions:
- An autonomous form expression (§15.2) with a type that is converted to a numerical type (§4.2, § 5.1.8).
Given that the rule for determining the type of the whole expression is defined as follows:
15.25.2. Numeric Conditional Expressions
Numeric conditional expressions are autonomous expressions (§15.2).
The type of numerical conditional expression is defined as follows:
If the second and third operands are of the same type, then this is a conditional expression type.
If one of the second and third operands has a primitive type T, and the type of the other is the result of applying the conversion of the box (section 5.1.7) to T, then the type of the conditional expression is T.
If one of the operands is of type byte or byte, and the other is of type short or Short, then the conditional expression type is short.
If one of the operands is of type T, where T is a byte, short or char, and the other operand is a constant expression (§15.28) of type int, whose value is represented in type T, then the conditional expression type is T.
If one of the operands is of type T, where T is Byte, Short, or Character, and the other operand is a constant expression of type int, whose value is represented in type U, which is the result of applying unboxing to T, then the conditional expression type is equal to U.
Otherwise, binary numeric promotion (§5.6.2) is used for operand types, and the conditional expression type is the advanced type of the second and third operands.
Note that binary numeric promotion performs a conversion on a set of values (§5.1.13) and can perform conversion for unpacking (§5.1.8).
Note that the fourth rule accurately describes the second example; the second operand is a constant of type int ( 0 ), and the third is char , so the conditional expression will evaluate to char . This will force the compiler to use the print(char) method, which will print y .
However, when you instead pass a variable instead of a constant, you come to the last rule, which states that "... the type of conditional expression is an advanced type of the second and third operands."
If you look at Section §5.6.2 of the JLS , it describes type promotion rules as follows:
When an operator applies binary numeric promotion to a pair of operands, each of which must indicate a value that can be converted to a numeric type, the following rules apply to:
If any operand has a reference type, it undergoes unpacking of the transformation (section 5.1.8).
The primitive conversion extension (§5.1.2) is used to convert one or both operands, as specified in the following rules:
If one of the operands is of type double, the other is converted to double.
Otherwise, if either operand is of type float, the other is converted to float.
Otherwise, if either operand is of type long, the other is converted to long.
Otherwise, both operands are converted to int type.
Following these rules, the type of the expression will be int , so the compiler will use the print(int) method, which will print 121 (ascii y value).