对您的问题的简短回答是,打印的值基于条件表达式计算的类型。
所以你的问题真的归结为,为什么条件表达式的类型不同
char y = 'y';
int i = 0;
System.out.print(false ? i : y); // prints 121
和
char y = 'y';
System.out.print(false ? 0 : y); // prints y
要回答这个问题,我们需要查看section §15.25 of the Java Language Specification。
Java 中的条件表达式分为三种:
由于int 和char 都可以转换为数值类型,因此根据此规则,该表达式是数值条件表达式的示例:
如果第二个和第三个操作数表达式都是数值表达式,则条件表达式是数值条件表达式。
为了对条件进行分类,以下表达式为数值表达式:
- 独立形式的表达式(第 15.2 节),其类型可转换为数字类型(第 4.2 节,第 5.1.8 节)。
因此,确定整个表达式的类型的规则如下:
15.25.2。数值条件表达式
数值条件表达式是独立的表达式(第 15.2 节)。
数值条件表达式的类型确定如下:
如果第二个和第三个操作数的类型相同,那么就是条件表达式的类型。
如果第二个和第三个操作数之一是原始类型 T,而另一个的类型是对 T 应用装箱转换(第 5.1.7 节)的结果,则条件表达式的类型为T.
如果其中一个操作数是byte或Byte类型,另一个是short或Short类型,则条件表达式的类型为short。
1234563条件表达式的类型是T。
如果其中一个操作数是 T 类型,其中 T 是 Byte、Short 或 Character,而另一个操作数是 int 类型的常量表达式,其值可在 U 类型中表示,U 是对T进行拆箱转换,则条件表达式的类型为U。
否则,二进制数值提升(第 5.6.2 节)应用于操作数类型,条件表达式的类型是第二个和第三个操作数的提升类型。
请注意,二进制数字提升执行值集转换(第 5.1.13 节)并可能执行拆箱转换(第 5.1.8 节)。
注意第四条规则准确地描述了第二个例子;第二个操作数是int (0) 类型的常量,第三个是char,因此条件表达式的计算结果为char。这将导致编译器使用print(char) 方法,该方法将打印y。
但是,当您改为传入 variable 而不是 constant 时,您会陷入最后一条规则,即“...条件表达式的类型是第二个和第三个操作数的提升类型。"
如果你看一下section §5.6.2 of the JLS,它描述了类型提升的规则如下:
当运算符对一对操作数应用二进制数值提升时,每个操作数都必须表示一个可转换为数值类型的值,按顺序适用以下规则:
如果任何操作数属于引用类型,则将对其进行拆箱转换(第 5.1.8 节)。
-
加宽原语转换(第 5.1.2 节)适用于转换以下规则中指定的一个或两个操作数:
如果任一操作数为 double 类型,则将另一个转换为 double。
否则,如果任一操作数为浮点型,则将另一个转换为浮点型。
否则,如果其中一个操作数是 long 类型,则另一个将转换为 long。
否则,两个操作数都转换为 int 类型。
通过遵循这些规则,表达式的类型将为int,因此编译器将使用print(int) 方法,该方法将打印121(y 的 ascii 值)。