Java如何在其16位字符类型中存储UTF-16字符?

时间:2012-10-28 19:57:00

标签: java variables unicode encoding utf-16

根据Java SE 7 Specification,Java使用Unicode UTF-16标准来表示字符。 当想象String作为16位变量的简单数组时,每个变量包含一个字符,生活很简单。

不幸的是,有些代码点只有16位是不够的(我相信它是所有Unicode字符的16/17)。所以在String中,这没有直接问题,因为当想要使用额外的两个字节存储其中一个~1.048.576个字符时,只需要{{1}中的两个数组位置将被使用。

这不会造成任何直接问题,适用于String,因为总有两个字节可以使用。虽然单变量与UTF-16编码相比,其固定长度为16位,但如何存储这些字符,特别是Java如何处理它的 2字节“char”类型

2 个答案:

答案 0 :(得分:24)

答案在the javadoc

  

char数据类型(因此是Character对象的值   encapsulates)基于原始的Unicode规范   将字符定义为固定宽度的16位实体。 Unicode   从那时起,标准被改为允许其角色   表示需要超过16位。

     

法律代码的范围   点现在是U + 0000到U + 10FFFF,称为Unicode标量值。   (请参阅Unicode标准中U + n表示法的定义。)   有时会引用从U + 0000到U + FFFF的字符集   作为基本多语言平面(BMP)。代码指向的字符   大于U + FFFF被称为补充字符。 Java   2平台使用char数组和中的UTF-16表示   String和StringBuffer类。在此表示中,补充   字符表示为一对char值,第一个来自   高代理范围,(\ uD800- \ uDBFF),第二个来自   低代理范围(\ uDC00- \ uDFFF)。

     

因此,char值   表示基本多语言平面(BMP)代码点,包括   代理代码点,或UTF-16编码的代码单元。一个int   value表示所有Unicode代码点,包括补充代码   点。 int的较低(最低有效)21位用于   表示Unicode代码点和上(最重要)11位   必须为零。

     

除非另有说明,否则相关的行为   补充字符和代理字符值如下:   只接受char值的方法不能支持补充   字符。他们将代理范围中的char值视为   未定义的字符。例如,Character.isLetter('\ uD840')   返回false,即使此特定值后跟any   字符串中的低代理值表示字母。方法   接受int值支持所有Unicode字符,包括   补充字符。例如,Character.isLetter(0x2F81A)   返回true,因为代码点值表示一个字母(一个CJK   表意文字)。在Java SE API文档中,Unicode代码点是   用于U + 0000和U + 10FFFF之间范围内的字符值,   和Unicode代码单元用于代码的16位字符值   UTF-16编码的单位。有关Unicode的更多信息   术语,请参阅Unicode词汇表。

简单地说:

  • char规则的16位是为旧版本的Unicode标准设计的
  • 你有时需要两个字符来表示一个不在Basic Multilingual Plane中的unicode符文(代码点)。这种“有效”是因为你不经常使用字符,尤其是处理BMP之外的unicode符文。

更简单的说:

  • java char不代表Unicode代码点(好吧,并非总是如此)。

顺便说一下,可以注意到Unicode扩展到BMP之后使得UTF-16全局无关,现在UTF-16甚至没有启用固定的字节字符比。这就是更多现代语言基于UTF-8的原因。这manifesto有助于理解它。

答案 1 :(得分:7)

基本上,字符串存储一系列UTF-16代码单元......这与存储Unicode代码点序列不同。

当需要基本多语种平面之外的字符时,它会占用String内的两个UTF-16代码单元。

大多数String操作 - length()charAtsubstring()等处理UTF-16代码单元的数量。但是,有codePointAt()之类的操作将处理完整的Unicode代码点......尽管索引仍以UTF-16代码单位表示。

编辑:如果你想在一个char中存储一个非BMP代码点,你基本上就不走运了。这就像是想在byte变量中存储超过256个不同的值......它只是不起作用。遵循在其他地方表示代码点的约定(例如在String中),最好只使用int变量。