根据爪哇SE 7规范 ,Java使用的Unicode UTF-16标准来表示的字符。 当想象一个String
作为各自包含一个字符的16位变量的简单阵列 ,寿命也很简单。
不幸的是,代码点这16位根本没有足够的(我相信这是所有Unicode字符的16/17)。 因此,在一个String
,这造成没有直接的问题,因为使用额外的两个字节想要存储的其中之一〜1.048.576字符时,因为根本就是两个阵列位置String
将被使用。
这,不构成任何直接的问题,适用于String
S,因为不可能永远是一个额外的两个字节。 虽然,当涉及到单一的变量,其在此相反的UTF-16编码,具有16个比特的固定长度 ,如何能这些字符被存储,并且特别是,如何Java使用2字节的“字符”做类型 ?
答案是的Javadoc :
char数据类型(因此,一个字符对象封装的值)是基于原始Unicode规范,其定义字符为固定宽度的16位实体。 Unicode标准已经被改变,以允许其表示需要多于16位的字符。
合法代码点的范围现在是U + 0000到U + 10FFFF,被称为Unicode标值。 (参考Unicode标准的U + n进制的定义。)的字符集从U + 0000到U + FFFF有时被称为基本多语种平面(BMP)。 字符中代码点大于U + FFFF称为增补字符。 在Java 2平台使用在字符数组和在字符串和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),因为该代码点值表示字母(a CJK表意文字)返回true。 在Java SE API文档,Unicode代码点用于字符值U + 0000和U + 10FFFF之间的范围内,和Unicode代码单元用于属于UTF-16编码的代码单元的16位char值。 有关Unicode术语的详细信息,请参阅Unicode的词汇。
简单地说:
- 对于一个char规则的16位是专为旧版本的Unicode标准
- 你有时需要两个字符来表示一个unicode符文(代码点),这是不是在基本多文种平面。 这kindof“作品”,因为你不经常使用的字符,特别是处理BMP之外的Unicode符文。
更简单的说:
- 一个Java字符并不代表一个Unicode编码点(当然,不总是)。
顺便说一句,它可以指出,统一的演变到延伸经过BMP由UTF-16全局无关,现在UTF-16甚至不使固定字节字符比。 这就是为什么越来越多的现代语言都是基于UTF-8。 该宣言有助于理解。
基本上,字符串存储的UTF-16编码单元的序列...这是不一样的存储Unicode代码点的序列。
当需要基本多语种平面以外的字符,即占用内的两个UTF-16代码单元String
。
大多数String
操作- length()
charAt
, substring()
等交易中的UTF-16编码单元号。 不过,也有类似的操作codePointAt()
将处理完整的Unicode代码点......虽然索引中的UTF-16编码单元方面依然表示。
编辑:如果您想将非BMP代码点存储在一个单一的char
,你基本上是出于运气。 这就像想要存储在超过256倍不同的值byte
变量...这是行不通的。 以下为表示代码点在其他地方(例如,在约定String
),最好只使用一个int
变量。