arrays.copyofrange是高效与简洁的平衡点,底层调用system.arraycopy实现快速拷贝,但频繁调用增加gc压力、超范围自动补默认值引入额外开销、对象数组仅拷贝引用;只读遍历时应直接索引访问而非拷贝。

Arrays.copyOfRange 是 Java 中最常用、最安全的数组截取方式,它不是“性能调优”的终点,而是高效与简洁的平衡点——用对了,既不用手写循环,也不用操心边界越界或目标数组创建;用错了,反而可能引入隐性开销或逻辑偏差。
为什么 copyOfRange 通常够快,但不该盲目迷信
它底层直接调用 JVM 的 System.arraycopy,属于 native 级内存块拷贝,性能接近硬件极限。但它的“快”是有前提的:
- 每次调用都会新建数组,频繁调用会增加 GC 压力(尤其在高频日志切片、分页循环中)
- 对超范围的
to值(如to > original.length)会自动补默认值,看似容错,实则多做一次长度判断和填充逻辑 - 对象数组拷贝的是引用,若后续修改原对象内容,新数组看到的仍是同一份数据——这不是性能问题,但可能引发意料外的副作用
真正影响性能的关键:何时不该用 copyOfRange
以下场景建议绕过 copyOfRange,改用更轻量或更可控的方式:
-
只读遍历某段数据:直接用原数组 + 循环索引控制(
for (int i = from; i ),零对象分配 -
固定大小缓冲区反复复用:比如网络接收包解析,用
System.arraycopy向已预分配的 byte[] 写入,避免每次 new 数组 -
字符串或字节数组切片:优先考虑
String.substring()(JDK 7u6+ 不共享底层数组)或ByteBuffer.slice(),它们是零拷贝视图操作
用好 copyOfRange 的三个实战细节
它本身足够简单,但几个细节决定是否“稳准快”:
-
索引务必左闭右开:
copyOfRange(arr, 2, 5)取的是下标 2、3、4,共 3 个元素;误写成to = 6就可能越界或结果多出一个空位 -
空数组安全,但别依赖它兜底:对
new int[0]调用copyOfRange(arr, 0, 0)返回空数组没问题,但若from或to是动态计算结果,仍需前置校验(如Math.max(0, from)) -
基本类型数组无深浅之分:int[]、double[] 拷贝后完全独立,可放心用于多线程防御性复制;而
StringBuilder[]类型则必须意识到——新数组里每个元素仍指向原来的 StringBuilder 实例
替代方案对比:什么情况下换方法更合适
不是所有截取都该用 copyOfRange,关键看需求重心:
-
要极致速度 + 复用缓冲区 → 选
System.arraycopy,自己 new 目标数组,显式控制起点偏移 -
只需完整拷贝或扩容 →
Arrays.copyOf(arr, newLen)更直观,比copyOfRange(arr, 0, newLen)语义更明确 -
一维对象数组且需隔离修改 → 单靠
copyOfRange不够,得配合手动 clone 每个元素,或用工具类做浅层深拷贝
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











