java中char是16位无符号整数,取值0–65535,固定占2字节,存储unicode bmp码点;超bmp字符用代理对表示,string字节数取决于编码而非char大小。

Java 中的 char 不是“字符的图片”,而是一个**16 位无符号整数**,取值范围是 0 到 65535(即 0x0000–0xFFFF),它直接对应 Unicode 基本多语言平面(BMP)里的码点。这个设计决定了它在内存中**固定占 2 字节**,和你存的是 'A' 还是 '中' 没关系。
char 存的是码点,不是字节流
当你写:
char c = '中';
编译器会查 Unicode 表,知道 '中' 的码点是 U+4E2D(十进制 20013),然后把这个数字以 16 位二进制形式(0100111000101101)存进内存——不经过 UTF-8、GBK 等编码转换,也不存原始字节。这个过程由源文件编码(如 UTF-8)→ 解码为 Unicode 码点 → 赋值给 char → 存为 16 位整数,全自动完成。
为什么必须是 2 字节?不是 1 字节,也不变长
- 1 字节最多表示 256 个字符,连常用汉字都不够
- 2 字节可表示 65536 种组合,刚好覆盖 BMP(Unicode 1.1 时代已足够)
- char 是基本类型,JVM 需要确定大小:用于数组连续存储、栈上快速偏移、内存对齐等底层操作
- 固定长度也支撑了 Java 的跨平台一致性——不管在哪台机器上,一个 char 永远是 2 字节
遇到 emoji 或生僻字怎么办?
像 ?(U+1F60A)这类超出 BMP 的字符,码点大于 0xFFFF,单个 char 放不下。Java 按 UTF-16 规则用两个 char 组成“代理对”:
- 高位代理(High Surrogate):0xD800–0xDBFF
- 低位代理(Low Surrogate):0xDC00–0xDFFF
- 它们合起来才表示一个完整字符,共占 4 字节内存
- 所以 "?".length() 返回 2,但真实字符数是 1;要用 String.codePointCount(0, s.length()) 才准确
别把 char 大小和字符串字节数搞混
char 占 2 字节,是指它在 JVM 内存中的存储大小。但 String 转成字节数组时,字节数取决于编码方式:
- "中".getBytes(StandardCharsets.UTF_8) → 3 字节(0xE4 0xB8 0xAD)
- "中".getBytes(StandardCharsets.UTF_16) → 4 字节(含 BOM,实际数据是 2 字节码点)
- "中".getBytes(StandardCharsets.ISO_8859_1) → 会丢数据,变成乱码(因该编码没定义中文)
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











