为什么我的字符打印为数字而不是字符?
根据Java三元运算符expression ? statement1 : statement2
expression ? statement1 : statement2
,如果expression
为true则执行statement1
,如果expression
为false则执行statement2
。
但是当我跑步时:
// some unnecessary codes not displaying char y = 'y'; int i = 0; System.out.print(false ? i : y);
我期待它打印y
但它的打印121
,为什么?
编辑根据manouti的答案,编译器解释为int
,但如果是这样,那么为什么我在i
看到死代码?
如果我做System.out.print(false ? 0 : x);
然后我得到y
,那么为什么在这种情况下编译器不会解释为int
?
对您的问题的简短回答是打印的值基于条件表达式求值的类型。
所以你的问题归结为,为什么条件表达式的类型不同
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
为了回答这个问题,我们需要看一下Java语言规范的第15.25节 。
Java中有三种类型的条件表达式:
- 布尔条件表达式
- 数字条件表达式
- 参考条件表达式
由于int
和char
都可以转换为数字类型,因此表达式是根据此规则的数值条件表达式的示例:
如果第二个和第三个操作数表达式都是数值表达式,则条件表达式是数字条件表达式。
为了对条件进行分类,以下表达式是数字表达式:
- 表达独立forms(第15.2节),其类型可转换为数字类型(§4.2,§5.1.8)。
鉴于此,确定整个表达式类型的规则如下:
15.25.2。 数字条件表达式
数字条件表达式是独立表达式(第15.2节)。
数字条件表达式的类型确定如下:
如果第二个和第三个操作数具有相同的类型,那么这就是条件表达式的类型。
如果第二个和第三个操作数之一是原始类型T,而另一个操作数的类型是对T应用装箱转换(第5.1.7节)的结果,那么条件表达式的类型是T.
如果其中一个操作数的类型为字节或字节,另一个操作数的类型为short或Short,则条件表达式的类型为short。
如果其中一个操作数是T类型,其中T是byte,short或char,另一个操作数是int类型的常量表达式(第15.28节),其值可以在类型T中表示,那么条件表达式的类型是T.
如果其中一个操作数是T类型,其中T是Byte,Short或Character,另一个操作数是int类型的常量表达式,其值可以在类型U中表示,这是将拆箱转换应用于T的结果,那么条件表达式的类型是U.
否则,二进制数字提升(第5.6.2节)将应用于操作数类型,条件表达式的类型是第二个和第三个操作数的提升类型。
请注意,二进制数字提升执行值集转换(第5.1.13节),并可执行拆箱转换(第5.1.8节)。
请注意,第四条规则准确描述了第二个例子; 第二个操作数是int
( 0
)类型的常量,第三个是char
,因此条件表达式将计算为char
。 这将导致编译器使用print(char)
方法,该方法将打印y
。
但是,当你改为传入一个变量而不是一个常量时 ,你可以归结为最后一条规则,即“……条件表达式的类型是第二个和第三个操作数的提升类型”。
如果您查看JLS的§5.6.2节 ,它将描述类型提升的规则,如下所示:
当运算符将二进制数字提升应用于一对操作数时,每个操作数必须表示可转换为数字类型的值,以下规则适用,顺序如下:
如果任何操作数是引用类型,则进行拆箱转换(第5.1.8节)。
应用扩展基元转换(第5.1.2节)来转换由以下规则指定的一个或两个操作数:
如果任一操作数的类型为double,则另一个操作数转换为double。
否则,如果任一操作数的类型为float,则另一个操作数转换为float。
否则,如果任一操作数的类型为long,则另一个操作数转换为long。
否则,两个操作数都将转换为int类型。
通过遵循这些规则,表达式的类型将为int
,因此编译器将使用print(int)
方法,该方法将打印121
( y
的ascii值)。
121
是字符y
的整数表示。 由于您将i
作为表达式的一部分提供,因此编译器将其解释为对System.out.print(int)
的调用,而不是System.out.print(char)
。
请注意,更改为System.out.print(false ? (char)i : y);
打印y
。
121是y的 ASCII代码,并且您已将i声明为整数,编译器也将y解释为int变量。 从而为y打印ASCII值。 编写System.out.print(false?(char)i:y)将打印y 。