2011-02-10 69 views
12

怎麼會出現這種情況:char轉換爲字節? (JAVA)

char a = '\uffff'; //Highest value that char can take - 65535 
byte b = (byte)a; //Casting a 16-bit value into 8-bit data type...! Isn't data lost here? 
char c = (char)b; //Let's get the value back 
int d = (int)c; 
System.out.println(d); //65535... how? 

基本上,我看到一個char是16位。因此,如果您將它投入byte,那麼如何避免數據丟失? (鑄造成int後的值相同)

在此先感謝您回答我這個小小的無知問題。 :P

編輯:哇,發現我的原始輸出實際上按預期做,但我只是更新上面的代碼。基本上,一個字符被轉換成一個字節,然後轉換回char,並保留其原始的2字節值。這是如何發生的?

+1

它爲我打印`-1`。 – darioo 2011-02-10 15:03:24

回答

19

正如trojanfoe所述,您對代碼結果的混淆部分是由於簽名擴展。我會嘗試添加更詳細的解釋,以幫助您解決困惑。

char a = '\uffff'; 
byte b = (byte)a; // b = 0xFF 

正如您所指出的那樣,這會導致信息丟失。這被認爲是narrowing conversion。將char轉換爲一個字節「只是丟棄n個最低位的所有位」。
結果是:0xFFFF -> 0xFF

char c = (char)b; // c = 0xFFFF 

轉換爲CHAR一個字節被認爲是一個special conversion。它實際上執行TWO轉換。首先,字節是SIGN-extended(新的高位從舊符號位複製)到一個int(一個正常的加寬轉換)。其次,int被轉換爲具有縮小轉換的字符。
結果是:0xFF -> 0xFFFFFFFF -> 0xFFFF

int d = (int)c; // d = 0x0000FFFF 

轉換一個字符爲int被認爲是一個widening conversion。當char類型被擴展爲整型時,它被零擴展(新的高位被設置爲0)。
結果是:0xFFFF -> 0x0000FFFF。打印時,這會給你65535.

我提供的三個鏈接是關於原始類型轉換的官方Java語言規範詳細信息。我強烈建議你看看。它們不是非常冗長(在這種情況下相對簡單)。它詳細說明了Java將在幕後進行類型轉換。這是許多開發人員常見的誤解。如果您仍然對任何步驟感到困惑,請發表評論。

0

一些相當奇怪的東西在你的機器上。在Java language specification, chapter 4.2.1看看:

的整數類型的值是 整數在以下範圍內:

對於字節,從-128到127,包容

...略其他...

如果您的JVM符合標準,那麼您的輸出應該是-1

5

java byte已簽名。這是違反直覺的。在幾乎所有使用字節的情況下,程序員都會想要一個無符號字節。如果一個字節直接轉換爲int,那麼它就很可能是一個bug。

這不正確的預期轉換幾乎所有的節目:

int c = 0xff & b ; 

根據經驗,符號字節的選擇是錯誤的。