chararrayreader 比 stringreader 内存开销更低,因其直接引用原始 char[] 而不复制;stringreader 每次构造都通过 system.arraycopy 创建新 char[],增加堆内存分配与 gc 压力。

CharArrayReader 比 StringReader 内存开销更低,核心差异在于是否复制字符数组——前者直接引用原始 char[],后者每次构造都隐式拷贝一份。
StringReader 会强制创建新 char[] 数组
它接收一个 String 对象,但不会复用其内部的 value 字段。JDK 实现中会执行一次 System.arraycopy,把字符串内容复制到自己新建的缓冲区里:
- 即使该
String刚由StringBuilder.toString()生成,也逃不过这次复制 - 10KB 的字符串 → 新分配约 20KB 堆内存(
char占 2 字节) - 每个
new StringReader(...)都产生一个独立char[]对象,加重 GC 压力
CharArrayReader 是真正的零拷贝
它只保存传入的 char[] 引用、当前位置 pos 和长度信息,不新建任何数组:
-
read()就是buf[pos++],纯下标访问,无对象创建 - 若
char[]来自StringBuilder.getChars()或反射获取,可完全跳过String中间态 - 同一块数组反复包装成
CharArrayReader,零额外分配
逃逸分析不能完全弥补 StringReader 的开销
虽然 JVM 可能将 StringReader 的临时 char[] 栈上分配(标量替换),但这依赖严格条件:
- 必须开启逃逸分析(默认开启,但复杂调用链下易失效)
- 不能被同步块、异常捕获、Lambda 引用等破坏逃逸判定
- 即便栈分配成功,数组复制本身仍发生,带来 CPU 缓存写入开销
适用场景建议
选 CharArrayReader 当:
- 数据源已经是
char[]或可低成本拿到(如StringBuilder内部数组) - 高频构建 Reader(如解析循环、高并发请求体处理)
- 对延迟敏感或堆内存紧张(如云原生轻量服务)
StringReader 更适合简单、低频、代码可读性优先的场景,比如原型开发或配置字符串一次性读取。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











