JDK 9 中 String 的内部存储结构由 char 数组改为 byte 数组,主要原因和设计考量是什么?
考察说明
考查候选人对 JDK 9 String 内部存储优化(Compact Strings)原理及动机的理解。
回答思路
- 【回答框架 1】JDK 9 引入 Compact Strings,将 String 内部的 char[] 改为 byte[],并增加一个编码标识字段(coder)。该字段表示当前字符串使用 LATIN1(单字节)还是 UTF16(双字节)编码。
- 【回答框架 2】核心动机是内存节省。Java 中 char 是 16 位无符号整数,若字符串仅包含 Latin-1 字符(如英文字母和常用符号),每个字符只需 1 字节,而 char[] 会固定占用 2 字节。改用 byte[] 后,Latin-1 字符串可节省约 50% 的内存。
- 【回答框架 3】实现方式:String 对象中保留 byte[] value 和 byte coder 字段。当 coder 为 0(LATIN1)时,每个字节代表一个字符;当 coder 为 1(UTF16)时,每两个字节代表一个 char。这样既支持非 Latin-1 字符,又对纯 ASCII 字符串实现压缩。
- 【回答框架 4】性能方面,内存占用降低有助于减少 GC 压力,提升缓存局部性,但字符串相关操作(如 indexOf、substring)需要根据 coder 选择不同实现分支,可能带来少量额外判断开销。整体上多数场景收益大于成本。
- 【关键点 1】内存节省:Latin-1 字符串内存占用减半。
- 【关键点 2】实现:byte[] + coder 字段,编码标识控制解码方式。
- 【关键点 3】兼容性:字符串不可变性不变,公共 API 行为不变。
- 【关键点 4】性能:减少 GC 和缓存压力,但操作需按编码分支处理。
- 【易错点 1】不要认为所有字符串都节省 50% 内存,仅当为 LATIN1 编码时有效。
- 【易错点 2】不要认为这是为了提升所有操作性能,有时分支判断会带来轻微开销。
- 【易错点 3】不要混淆 Compact Strings 与字符串常量池(StringTable)的机制。