Java中char是16位无符号整数,取值0–65535,仅能表示Unicode基本多文种平面(BMP)字符;超出BMP的辅助平面字符需用UTF-16代理对(两个char)表示,操作时应使用codePoint相关API而非charAt等char级方法。

Java 中的 char 类型本质上是一个 16 位无符号整数,取值范围是 0 到 65535(即 0x0000 到 0xFFFF),它最初被设计为直接对应 Unicode 基本多文种平面(BMP, Basic Multilingual Plane)中的一个字符。但随着 Unicode 标准扩展,大量字符(如 emoji、古汉字、部分少数民族文字)被放入辅助平面(Supplementary Planes),超出了 char 的表示能力——这就引出了 char 与 Unicode 编码之间既紧密又受限的关系。
char 只能表示 BMP 内的 Unicode 码点
Unicode 将字符映射到称为“码点”(code point)的整数值上,例如 'A' 是 U+0041,'中' 是 U+4E2D。BMP 覆盖了 U+0000 到 U+FFFF,恰好可用一个 char 存储。因此,所有 ASCII 字符、常见汉字、拉丁字母、希腊字母等都在此范围内,用 char 表示毫无问题。
但像 ?(U+1F30D)、?(U+1FAB7)或某些生僻汉字(如 U+20000 以上的“?”)都位于辅助平面(U+10000 ~ U+10FFFF),无法用单个 char 表示。
超出 BMP 的字符需用两个 char 表示(代理对)
Java 采用 UTF-16 编码方案存储字符串。对于辅助平面的码点,UTF-16 使用一对 16 位值:一个高位代理(high surrogate,范围 U+D800–U+DBFF)和一个低位代理(low surrogate,范围 U+DC00–U+DFFF)。这两个 char 合起来才表示一个完整字符。
立即学习“Java免费学习笔记(深入)”;
- 例如:U+1F30D(?)被编码为 0xD83C 和 0xDF0D 两个 char
- String.length() 返回的是 char 数量,不是字符数;对含 emoji 的字符串调用 length() 可能返回 2,但实际只含 1 个字符
- 使用 String.codePointCount(0, str.length()) 才能得到真实字符数
操作字符应优先使用 codePoint 相关 API
直接对 char 进行遍历或判断容易出错,尤其在处理 emoji 或扩展汉字时。Java 提供了基于码点的操作方法:
- 用 String.codePointAt(int index) 替代 charAt() 获取指定位置的完整码点(返回 int)
- 用 String.offsetByCodePoints(int start, int offset) 安全跳过一个或多个字符
- 用 Character.isSupplementaryCodePoint(int cp) 判断是否为辅助平面码点
- 用 Character.toChars(int cp) 将码点转为 char 数组(可能长度为 1 或 2)
char 本质是数值,不是“字符对象”
char 是基本类型,不带语义。它可参与算术运算(如 'a' + 1 → 'b'),也可强制转换为 int 查看其 Unicode 值(如 (int)'中' 得 20013)。但要注意:把一个辅助平面码点强行转成 char 会丢失高位信息,仅保留低 16 位,结果不可预测。
例如:(char)0x1F30D 实际得到的是 0xF30D(即 U+F30D,一个完全无关的私用区字符),而非 ?。










