2015-06-27 48 views
3

我正在嘗試從int值得到char值>0xFFFF。但相反,我總是得到相同的值,當投射到int時,打印值爲655350xFFFF)。將int轉換爲char,然後返回int - 並不總是給出相同的結果

我不明白爲什麼它會爲unicode>0xFFFF生成符號。我想預計產量是0x10FFFF。相反,輸出爲65535

+2

什麼是你期待?你知道'int'和'char'的區別嗎? –

+0

是的,我知道區別,但我想生成一個字符,其UTF8編碼給我4個字節,我沒有做到。 –

回答

3

這是因爲,雖然int是4個字節,但char只有2個字節。因此,您不能在char中表示您可以在int中的所有值。使用標準的無符號整數表示法,您只能表示從02^16 - 1 == 65535兩個字節值的值範圍,因此如果將該範圍外的任何數字轉換爲2字節值並返回,則會丟失數據。

2

int是4字節。 char是2個字節。 你的號碼在int可以保持的範圍內,但不是哪個char可以。 所以,當你把這個數字轉換成字符時,它會丟失數據並且成爲字符可容納的最大值,這就是它所打印的數據,即65535

2

你的號碼太大而不能成爲2字節的字符。但它足夠小,適合作爲4字節的int。 65535是適合char的最大數量,所以這就是爲什麼你有這個價值。另外,如果一個字符足夠大以適合你的號碼,當你將它返回給int時,它可能已經返回了0x10FFFF的十進制值,即1114111.

2

不幸的是,我認爲你期待Java char成爲與Unicode代碼點相同。它們不是同一件事。

Java char,如其他答案所表達的,只能支持可以用16位表示的代碼點,而Unicode需要21位來支持所有的代碼點。

換句話說,一個Java自己的char只支持基本多語言平面字符(代碼點< = 0xFFFF)。在Java中,如果要表示位於其中一個擴展平面中的Unicode代碼點(代碼點>0xFFFF),則需要代理字符或一對字符來完成此操作。這是UTF-16的工作原理。而且,在內部,這也是Java字符串的工作方式。只是爲了好玩,運行下面的代碼片段,看看如何單個Unicode代碼點實際上是由2個字符表示,如果代碼點是>0xFFFF

// Printing string length for a string with 
// a single unicode code point: 0x22BED. 
System.out.println("".length()); // prints 2, because it uses a surrogate pair. 

如果你想安全地轉換的int值,表示一個Unicode代碼指向一個char(或char使他能更準確),然後將其轉換回一個int碼點,你將不得不使用這樣的代碼:

public static void main(String[] args) { 
    int hex = 0x10FFFF; 
    System.out.println(Character.isSupplementaryCodePoint(hex)); // prints true because hex > 0xFFFF 
    char[] surrogateChars = Character.toChars(hex); 
    int codePointConvertedBack = Character.codePointAt(surrogateChars, 0); 
    System.out.println(codePointConvertedBack); // prints 1114111 
} 

或者,而不是操縱char一rrays,您可以使用String,像這樣:

public static void main(String[] args) { 
    int hex = 0x10FFFF; 
    System.out.println(Character.isSupplementaryCodePoint(hex)); // prints true because hex > 0xFFFF 
    String s = new String(new int[] {hex}, 0, 1); 
    int codePointConvertedBack = s.codePointAt(0); 
    System.out.println(codePointConvertedBack); // prints 1114111 
} 

對於進一步閱讀:Java Character Class