[英]Output different from what i have expected
為何打印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);
}
在第一個print
語句中,條件表達式的類型是char(即'X'),因為JLS的第15.25部分(約為條件表達式的類型)適用於:
如果其中一個操作數是T類型,其中T是byte,short或char,另一個操作數是int類型的常量表達式,其值可以在類型T中表示,那么條件表達式的類型是T.
所以第一個語句打印“X”。
在第二個print
語句中,該部分不適用,因為i
不是常量表達式。 相反,本節適用:
否則,二進制數字提升(第5.6.2節 )將應用於操作數類型,條件表達式的類型是第二個和第三個操作數的提升類型。 請注意,二進制數字促銷執行拆箱轉換(第5.1.8節)和值集轉換(第5.1.13節)。
二進制數字提升將char'X'轉換為int(88),第二個語句打印“88” - 因此“X88”的整體結果。
它在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.1.13節)。
這適用於第二種,因為沒有別的。 :) §5.6.2中的相關規則很簡單:
否則,兩個操作數都將轉換為int類型。
'X'的Unicode代碼點是88。
對於第一個語句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(因為編譯器知道不會丟失精度)。
資源:
因為表達式false ? i : x
false ? i : x
被視為由編譯器返回一個整數。 由於您使用的是char
因此'X'在ASCII中為88,因為它們是兼容的,所以它被視為整數。
就個人而言,我認為這里至少應該有一個編譯器警告。
在第二個三元組If中,參數必須是相同的類型,否則兩個中的一個是隱式轉換的。
在您的示例中,x從char轉換為int,而'X'的ASCII代碼為88。
其他人已經回答了為什么會這樣。
如果要打印X
,請將表達式值轉換回char
:
System.out.print((char)(false ? i : x)); // prints X
或者您也可以將i
為char
以便表達式的類型變為char
:
System.out.print(false ? (char)i : x); // prints X
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.