char 是 UTF-16 代码单元,仅能直接表示 BMP 内码点(U+0000–U+FFFF),超出处需代理对;它不是语义字符,单个 char 不恒等于一个用户感知的字符。

char 类型本身不“拥有”Unicode编码列表,它只是 Java、C# 等语言中用来存储一个 UTF-16 代码单元(code unit) 的 16 位数据类型。它的取值范围固定为 0x0000 到 0xFFFF(即 0–65535),对应 Unicode 的基本多文种平面(BMP)。这个范围内的每个数值,如果被解释为字符,就可能映射到一个 Unicode 码点(code point)——但仅限 BMP 内的码点。
char 能直接表示的 Unicode 区间(BMP,U+0000–U+FFFF)
这是 char 可以单个容纳的所有码点,共 65536 个。常见区块包括:
- U+0000–U+007F:ASCII(控制符 + 英文字母、数字、标点)
- U+0080–U+00FF:Latin-1 Supplement(带重音的西欧字符,如 é, ñ, ü)
- U+0370–U+03FF:希腊字母与科普特文(α, β, Γ, Δ)
- U+0400–U+04FF:西里尔字母(А, Б, В, Г)
- U+0590–U+05FF:希伯来文
- U+0600–U+06FF:阿拉伯文
- U+4E00–U+9FFF:常用汉字(约 2 万多个,如 中、国、程、序)
- U+3400–U+4DBF:扩展 A 区汉字(生僻字,部分需代理对支持显示)
- U+3000–U+303F:CJK 标点与符号( 、,、。、!、?)
- U+1F600–U+1F64F:表情符号(?、?、?)——⚠️注意:这些码点 超出 BMP(U+1F600 = 128512 > 65535),不能用单个 char 表示
char 无法单独表示的 Unicode 码点(增补平面)
Unicode 当前定义了 17 个平面(0x00–0x10),但只有第 0 平面(BMP)能被单个 char 直接映射。其余平面(如第 1 平面 U+10000–U+1FFFF)中的字符,例如:
- 大部分 Emoji:?(U+1F60E)、?(U+1FAF5)
- 扩展汉字:?(U+30000)、?(U+30087)
- 古文字、数学符号扩展区等
这些码点数值 ≥ 0x10000,已超过 char 的最大值 0xFFFF。Java 和 C# 通过 代理对(surrogate pair) 处理:用两个连续的 char(高代理项 + 低代理项)共同编码一个码点。此时,单个 char 不再对应逻辑字符,仅是编码中间产物。
如何查某个字符对应的 char 行为?
不要依赖“字符看起来像一个”,而要看其实际码点:
- 在 Java 中用
String.codePointAt(0)或Character.codePointCount(str, 0, str.length())获取真实码点 - 用
Character.isSurrogate(char c)判断该 char 是否属于代理项 - 用
Character.toCodePoint(high, low)将一对代理 char 还原为码点 - 在线工具推荐:Unicode.org 官方字符搜索(https://unicode.org/cldr/utility/character.jsp)或 fileformat.info
关键提醒:char ≠ 字符
这是一个常被误解的核心点:
- char 是 存储单位(UTF-16 code unit),不是语义上的“字符”
- 一个用户感知的“字”或“表情”,可能由 1 个 char(BMP)或 2 个 char(代理对)构成
- 对字符串做
charAt(i)或遍历toCharArray(),拿到的是代码单元,不是码点;处理文本时务必优先使用codePoints()流

















