簡體   English   中英

Java如何在其16位字符類型中存儲UTF-16字符?

[英]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術語表。

簡單地說:

  • char規則的16位是為舊版本的Unicode標准設計的
  • 你有時需要兩個字符來表示一個不在基本多語言平面中的unicode符文(代碼點)。 這種“有效”因為你不經常使用字符,尤其是處理BMP之外的unicode符文。

更簡單的說:

  • java char不代表Unicode代碼點(嗯,並非總是如此)。

順便說一下,可以注意到Unicode的演變超過了BMP,使得UTF-16在全球范圍內無關緊要,因為UTF-16甚至不能實現固定的字節字符比。 這就是更多現代語言基於UTF-8的原因。 這個宣言有助於理解它。

基本上,字符串存儲一系列UTF-16代碼單元......這與存儲一系列Unicode代碼點不同。

當需要基本多語言平面之外的字符時,它在String中占用兩個UTF-16代碼單元。

大多數String操作 - length()charAtsubstring()等處理UTF-16代碼單元的數量。 但是,像codePointAt()這樣的操作將處理完整的Unicode代碼點......盡管索引仍然以UTF-16代碼單位表示。

編輯:如果你想在一個char存儲一個非BMP代碼點,你基本上是運氣不好。 這就像是想在一個byte變量中存儲超過256個不同的值......它只是不起作用。 遵循在其他地方表示代碼點的約定(例如在String ),最好只使用int變量。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM