为什么我的字符打印为数字而不是字符?

根据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中有三种类型的条件表达式:

  • 布尔条件表达式
  • 数字条件表达式
  • 参考条件表达式

由于intchar都可以转换为数字类型,因此表达式是根据此规则的数值条件表达式的示例:

如果第二个和第三个操作数表达式都是数值表达式,则条件表达式是数字条件表达式。

为了对条件进行分类,以下表达式是数字表达式:

  • 表达独立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节)。

请注意,第四条规则准确描述了第二个例子; 第二个操作数是int0 )类型的常量,第三个是char ,因此条件表达式将计算为char 。 这将导致编译器使用print(char)方法,该方法将打印y

但是,当你改为传入一个变量而不是一个常量时 ,你可以归结为最后一条规则,即“……条件表达式的类型是第二个和第三个操作数的提升类型”。

如果您查看JLS的§5.6.2节 ,它将描述类型提升的规则,如下所示:

当运算符将二进制数字提升应用于一对操作数时,每个操作数必须表示可转换为数字类型的值,以下规则适用,顺序如下:

  1. 如果任何操作数是引用类型,则进行拆箱转换(第5.1.8节)。

  2. 应用扩展基元转换(第5.1.2节)来转换由以下规则指定的一个或两个操作数:

    • 如果任一操作数的类型为double,则另一个操作数转换为double。

    • 否则,如果任一操作数的类型为float,则另一个操作数转换为float。

    • 否则,如果任一操作数的类型为long,则另一个操作数转换为long。

    • 否则,两个操作数都将转换为int类型。

通过遵循这些规则,表达式的类型将为int ,因此编译器将使用print(int)方法,该方法将打印121y的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