[英]How does Java store UTF-16 characters in its 16-bit char type?
根據Java SE 7規范 ,Java使用Unicode UTF-16標准來表示字符。 將String
想象成一個包含一個字符的16位變量的簡單數組時,生活很簡單。
不幸的是,有16位的代碼點是不夠的(我相信它是所有Unicode字符的16/17)。 所以在String
,這沒有直接問題,因為當想要使用額外的兩個字節存儲這些~1.048.576個字符中的一個時,將只使用該String
兩個數組位置。
這沒有任何直接問題,適用於String
,因為總有一個額外的兩個字節。 雖然單變量與UTF-16編碼相比,具有16位的固定長度 ,但是如何存儲這些字符,特別是Java如何使用其2字節“char”來完成類型 ?
答案在javadoc中 :
char數據類型(以及Character對象封裝的值)基於原始Unicode規范,該規范將字符定義為固定寬度的16位實體。 此后,Unicode標准已更改為允許表示形式需要16位以上的字符。
合法代碼點的范圍現在是U + 0000到U + 10FFFF,稱為Unicode標量值。 (請參閱Unicode標准中U + n表示法的定義。)U + 0000到U + FFFF的字符集有時稱為基本多語言平面(BMP)。 代碼點大於U + FFFF的字符稱為增補字符。 Java 2平台在char數組和String和StringBuffer類中使用UTF-16表示。 在此表示中,補充字符表示為一對char值,第一個來自高代理范圍(\\ uD800- \\ uDBFF),第二個來自低代理范圍(\\ uDC00- \\ uDFFF)。
因此,char值表示基本多語言平面(BMP)代碼點,包括代理代碼點或UTF-16編碼的代碼單元。 int值表示所有Unicode代碼點,包括補充代碼點。 int的較低(最低有效)21位用於表示Unicode代碼點,而較高(最高有效)11位必須為零。
除非另有說明,否則關於補充字符和代理char值的行為如下:僅接受char值的方法不能支持增補字符。 它們將代理范圍中的char值視為未定義的字符。 例如,Character.isLetter('\\ uD840')返回false,即使后面跟着字符串中的任何低代理值的特定值也表示字母。 接受int值的方法支持所有Unicode字符,包括補充字符。 例如,Character.isLetter(0x2F81A)返回true,因為代碼點值表示一個字母(CJK表意文字)。 在Java SE API文檔中,Unicode代碼點用於U + 0000和U + 10FFFF之間的字符值,Unicode代碼單元用於16位字符值,這些值是UTF-16編碼的代碼單元。 有關Unicode術語的更多信息,請參閱Unicode術語表。
簡單地說:
更簡單的說:
順便說一下,可以注意到Unicode的演變超過了BMP,使得UTF-16在全球范圍內無關緊要,因為UTF-16甚至不能實現固定的字節字符比。 這就是更多現代語言基於UTF-8的原因。 這個宣言有助於理解它。
基本上,字符串存儲一系列UTF-16代碼單元......這與存儲一系列Unicode代碼點不同。
當需要基本多語言平面之外的字符時,它在String
中占用兩個UTF-16代碼單元。
大多數String
操作 - length()
, charAt
, substring()
等處理UTF-16代碼單元的數量。 但是,像codePointAt()
這樣的操作將處理完整的Unicode代碼點......盡管索引仍然以UTF-16代碼單位表示。
編輯:如果你想在一個char
存儲一個非BMP代碼點,你基本上是運氣不好。 這就像是想在一個byte
變量中存儲超過256個不同的值......它只是不起作用。 遵循在其他地方表示代碼點的約定(例如在String
),最好只使用int
變量。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.