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

roc*_*ing 6 java int char

根据Java三元运算符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);
Run Code Online (Sandbox Code Playgroud)

我期待它打印,y但它的打印121,为什么?

编辑 根据manouti的答案,编译器解释为int,但如果是这样,那么为什么我看到死代码i

如果我这样做,System.out.print(false ? 0 : x);那么我得到了y,那么为什么在这种情况下编译器不会解释为int

man*_*uti 10

121是字符的整数表示y.由于您i作为表达式的一部分提供,因此编译器将其解释为调用System.out.print(int)而不是System.out.print(char).

请注意,更改为System.out.print(false ? (char)i : y);打印y.


azu*_*rog 3

您的问题的简短答案是打印的值基于条件表达式计算的类型。

\n\n

所以你的问题实际上可以归结为,为什么条件表达式的类型在不同之间有所不同

\n\n
char y = \'y\';\nint i = 0;\nSystem.out.print(false ? i : y); // prints 121\n
Run Code Online (Sandbox Code Playgroud)\n\n

\n\n
char y = \'y\';\nSystem.out.print(false ? 0 : y); // prints y\n
Run Code Online (Sandbox Code Playgroud)\n\n

要回答这个问题,我们需要查看Java 语言规范 的 \xc2\xa715.25 部分

\n\n

Java中的条件表达式分为三种类型:

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

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

\n\n
\n

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

\n\n

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

\n\n
    \n
  • 独立形式 (\xc2\xa715.2) 的表达式,其类型可转换为数字类型 (\xc2\xa74.2、\xc2\xa75.1.8)。
  • \n
\n
\n\n

鉴于此,确定整个表达式类型的规则如下:

\n\n
\n

15.25.2。数字条件表达式

\n\n

数字条件表达式是独立表达式 (\xc2\xa715.2)。

\n\n

数值条件表达式的类型确定如下:

\n\n
    \n
  • 如果第二个和第三个操作数具有相同的类型,则这就是条件表达式的类型。

  • \n
  • 如果第二个和第三个操作数之一是原始类型 T,而另一个操作数的类型是对 T 应用装箱转换 (\xc2\xa75.1.7) 的结果,则条件表达式的类型为 T。

  • \n
  • 如果其中一个操作数的类型为 byte 或 Byte,另一个操作数的类型为 Short 或 Short,则条件表达式的类型为 Short。

  • \n
  • 如果其中一个操作数是 T 类型,其中 T 是 byte、short 或 char,而另一个操作数是 int 类型的常量表达式 (\xc2\xa715.28),其值可以用类型 T 表示,则条件表达式为T。

  • \n
  • 如果其中一个操作数是 T 类型,其中 T 是 Byte、Short 或 Character,另一个操作数是 int 类型的常量表达式,其值可以用类型 U 表示,U 类型是对 T 应用拆箱转换的结果,则条件表达式的类型为 U。

  • \n
  • 否则,将对操作数类型应用二进制数值提升 (\xc2\xa75.6.2),并且条件表达式的类型是第二个和第三个操作数的提升类型。

  • \n
\n\n

请注意,二进制数字提升执行值集转换 (\xc2\xa75.1.13),并且可能执行拆箱转换 (\xc2\xa75.1.8)。

\n
\n\n

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

\n\n

然而,当您传入变量而不是常量时,您会陷入最后一条规则,即“...条件表达式的类型是第二个和第三个操作数的提升类型”。

\n\n

如果您查看JLS 的 \xc2\xa75.6.2 部分,它描述了类型提升的规则,如下所示:

\n\n
\n

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

\n\n
    \n
  1. 如果任何操作数是引用类型,则对其进行拆箱转换(\xc2\xa75.1.8)。

  2. \n
  3. 加宽基元转换 (\xc2\xa75.1.2) 用于按照以下规则指定转换一个或两个操作数:

    \n\n
      \n
    • 如果其中一个操作数的类型为 double,则另一个操作数将转换为 double。

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

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

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

    • \n
  4. \n
\n
\n\n

通过遵循这些规则,表达式的类型将为int,因此编译器将使用该print(int)方法,该方法将打印121( 的 ascii 值y)。

\n