Java中char是16位UTF-16编码单元,可表示BMP字符(如'中'),但辅助平面字符(如?)需代理对;操作字符串应使用codePointCount、codePoints等API而非charAt/length。

Java 中的 char 是16位无符号整数类型,用于表示单个 Unicode 字符,底层采用 UTF-16 编码规则。它不是 ASCII 的简单扩展,而是能表达更广泛字符(包括中文、emoji、数学符号等)的基础类型。
char 的本质:UTF-16 编码单元
char 在 JVM 内部占 2 字节(0x0000 ~ 0xFFFF),对应一个 UTF-16 编码单元(code unit)。注意:它不等于“一个字符(character)”——某些 Unicode 字符(如大部分 emoji 或古汉字)需要两个 char(即一个代理对,surrogate pair)才能完整表示。
- 基本多文种平面(BMP,U+0000 ~ U+FFFF)内的字符:用 1 个
char表示,例如'A'、'中'、'€' - 辅助平面(U+10000 及以上)的字符:需用 2 个
char组成代理对,例如 ?(U+1F30D)→'\uD83C'+'\uDF0D' - 直接写法:
char c = '中';、char c = '\u4F26';(Unicode 转义)、char c = 20013;(十进制码点值)
char 与字符串、码点的正确交互
用 String 处理字符时,不能简单依赖 charAt() 或 length() 来统计“字符个数”,因为它们操作的是 char 单元,而非逻辑字符(grapheme cluster)。
-
"?".length()返回 2(两个char),但实际是 1 个字符 - 获取真实字符数:用
string.codePointCount(0, string.length()) - 安全遍历字符:用
string.codePoints().forEach(...)或手动配合Character.isHighSurrogate()/isLowSurrogate() - 从码点构造字符:若码点 ≤ 0xFFFF,可用
(char) codePoint;否则需拆为代理对,推荐用Character.toChars(codePoint)返回char[]
常见误区与注意事项
开发中容易忽略 char 的 UTF-16 特性,导致乱码或越界问题。
立即学习“Java免费学习笔记(深入)”;
- 误把
char当作“字节”:它永远是 2 字节,和文件编码(如 UTF-8)无关;读写文本时应使用InputStreamReader/OutputStreamWriter指定 charset - 字符串拼接中混用
char和int:如'a' + 1结果是98(int 类型),不是'b';要转回 char 需显式强转:(char)('a' + 1) - 正则或比较时忽略代理对:如
String.substring()可能切开代理对,造成无效字符;建议用String.offsetByCodePoints()定位 - JSON/网络传输中:Java
char序列化为 JSON 字符串时,会自动转义非 ASCII 字符(如"\u4F26"),无需手动处理
实用小技巧
快速验证和调试 char 相关逻辑:
- 打印字符的 Unicode 码点:
System.out.printf("U+%04X%n", (int)'中'); - 判断是否为代理对中的高/低位:
Character.isSurrogate(c)、Character.isHighSurrogate(c) - 将字符串转为码点流查看:
str.codePoints().mapToObj(Integer::toHexString).forEach(System.out::println); - 安全截取前 N 个字符(按逻辑字符):
str.substring(0, str.offsetByCodePoints(0, N));










