码点(Code Point) 是 Unicode 标准中为每一个"字符"分配的唯一数字编号。
你可以把它理解为字符在 Unicode 这个"超级字典"里的身份证号。不管这个字符用什么编码方式存储(UTF-8、UTF-16、UTF-32),它的码点永远不变。
🔢 长什么样
码点通常用 U+ 前缀加十六进制数表示:
| 字符 | 码点 | 说明 |
|---|---|---|
A |
U+0041 | 基本拉丁字母 |
中 |
U+4E2D | CJK 统一汉字 |
😀 |
U+1F600 | 增补平面 emoji |
𝄞 |
U+1D11E | 音乐符号 |
💡 关键认知 :码点是抽象的逻辑概念 ,和具体的字节存储无关。
U+1F600就是"笑脸"这个字符本身,至于它占 2 个 char 还是 4 个字节,那是编码方案的事。
🆚 码点 vs char vs 字节
这是最容易混淆的三个概念:
| 概念 | 本质 | 大小 | 例子(😀) |
|---|---|---|---|
| 码点 | 字符的唯一编号 | 0 ~ 0x10FFFF | U+1F600 |
| char | Java/UTF-16 的编码单元 | 固定 16 bit | \uD83D\uDE00(两个 char) |
| 字节 | 实际存储/传输的最小单位 | 取决于编码 | UTF-8: 4字节;UTF-16: 4字节 |
一句话区分:
- 码点 回答的是"这是什么字符?"
- char/字节 回答的是"怎么存/怎么传?"
📐 Unicode 的码点空间
Unicode 定义了 0x0 ~ 0x10FFFF 共 1,114,112 个码点位置,分为 17 个平面:
- BMP(基本多文种平面) :U+0000 ~ U+FFFF → 包含中文、英文、日文等常用字符 → 1 个 char 就能表示
- 增补平面(1~16) :U+10000 ~ U+10FFFF → 包含 emoji、生僻字、历史文字等 → 需要 2 个 char(代理对)才能表示
这就是你之前学代理对的根源:码点空间大于单个 char 的表达能力,所以超出 BMP 的码点必须用两个 char 来编码。
🎯 为什么你需要关心码点
因为所有字符串操作的语义都应该基于码点,而不是 char:
- "用户名最多10个字" → 10 个码点,不是 10 个 char
- "截取前5个字符" → 前 5 个码点
- "这个字符串有几个字" → 码点数量
- 数据库
VARCHAR(10)→ 不同数据库行为不同,有的按码点,有的按字节,必须确认
📌 终极记忆 :码点 = 字符 = 用户眼中的"一个字"。写代码时,凡是涉及"字符数"的逻辑,脑子里想的应该是码点,而不是
char。