为什么打印X88
public static void main(String [] args)
{
char x = 'X';
int i = 0;
System.out.print(true ? x : 0);
System.out.print(false ? i : x);
}
答案 0 :(得分:5)
在第一个print
语句中,条件表达式的类型是char(即'X'),因为section 15.25 of the JLS的这一部分(大约是条件表达式的类型)适用:< / p>
如果其中一个操作数是T类型,其中T是byte,short或char,另一个操作数是int类型的常量表达式,其值可以在类型T中表示,那么条件表达式的类型是T
所以第一个语句打印“X”。
在第二个print
语句中,该部分不适用,因为i
不是常量表达式。相反,本节适用:
否则,二进制数字提升(§5.6.2)将应用于操作数类型,条件表达式的类型是第二个和第三个操作数的提升类型。请注意,二进制数字促销执行拆箱转换(第5.1.8节)和值集转换(第5.113节)。
二进制数字提升将char'X'转换为int(88),第二个语句打印“88” - 因此“X88”的整体结果。
答案 1 :(得分:4)
在JLS的§15.25中对此进行了解释。
否则,如果是第二个和第三个 操作数有类型 可转换(第5.1.8节)到数字类型, 那么有几种情况:
这适用于两个语句,因为char和int都是数字类型,因此5.1.8非常适用。所以我们看下面的规则(摘录):
[...]
- 如果其中一个操作数是T类型,其中T是byte,short或 char,另一个操作数是 int类型的常量表达式 值可以在类型T中表示 条件表达式的类型 是T。
这适用于第一个,因为0是int类型的常量表达式。 T是,char
,这就是它打印为X的原因。
[...]
- 否则,二进制数字促销(§5.6.2)将应用于 操作数类型和类型 条件表达式是升级的 第二个和第三个操作数的类型。 注意二进制数字促销 执行拆箱转换(§5.1.8) 和价值集转换(第5.113节)。
这适用于第二个,因为没有别的。 :)来自§5.6.2的相关规则很简单:
否则,两个操作数都将转换为int类型。
'X'的Unicode代码点是88。
答案 2 :(得分:1)
对于第一个语句System.out.print(false ? x : 0);
,编译器认为您要打印一个char,因此0将被视为char(在编译期间)。
执行System.out.print(false ? i : x);
时,编译器认为您要打印一个整数,因此它会尝试将(加宽)'X'转换为88的整数。
有趣的是,如果你尝试这样做:
System.out.print(true ? x : i);
由于i
不能被视为一个字符(它需要缩小),它将打印88
另一件令人沮丧的事情是:
System.out.print(true ? x : 65536);
这次在编译时不能将值65536
视为char(char的最大值为65535
[@See Character.MAX_VALUE])因此它将被视为一个int,所以x也是。
总而言之,如果操作数之一是int而另一个是char,则有两种可能的转换:
为了避免无用的损失,Java将选择第二个选项。
执行System.out.print(false ? x : 0);
时,0会在编译时转换为char(因为编译器知道不会丢失精度)。
资源:
答案 3 :(得分:0)
因为表达式false ? i : x
被编译器视为返回一个整数。由于您使用char
,因此'X'在ASCII中为88,因为它们是兼容的,所以它被视为整数。
就个人而言,我认为这里至少应该有一个编译器警告。
答案 4 :(得分:0)
在第二个三元组If中,参数必须是相同的类型,否则两个中的一个是隐式转换的。
在您的示例中,x从char转换为int,而'X'的ASCII代码为88.
答案 5 :(得分:0)
其他人已经回答了为什么会这样。
如果您希望打印X
,请将表达式值转换回char
:
System.out.print((char)(false ? i : x)); // prints X
或者您也可以将i
投射到char
,以便表达式的类型变为char
:
System.out.print(false ? (char)i : x); // prints X