答案在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 位 char 值,它们是 UTF-16 编码的代码单元。有关 Unicode 术语的更多信息,请参阅 Unicode 词汇表。
简单地说:
- char 规则的 16 位是为旧版本的 Unicode 标准设计的
- 您有时需要两个字符来表示不在基本多语言平面中的 unicode 符文(代码点)。这种“有效”是因为您不经常使用字符,尤其是在处理 BMP 之外的 unicode 符文时。
更简单的说:
- java char 不代表 Unicode 代码点(嗯,并非总是如此)。
顺便说一句,可以注意到 Unicode 超越 BMP 的演变使得 UTF-16 在全球范围内变得无关紧要,因为 UTF-16 甚至不支持固定的字节字符比率。这就是为什么更现代的语言基于 UTF-8。这份宣言有助于理解它。