arrays.copyofrange 创建新数组且不修改原数组,参数 from(含)到 to(不含),越界抛 arrayindexoutofboundsexception;返回独立副本,非视图,泛型擦除下基本类型与引用类型行为一致,底层用 system.arraycopy 实现,时间空间复杂度均为 o(n)。

copyOfRange 会创建新数组,原数组完全不受影响
这是最常被误解的一点:Arrays.copyOfRange 从不修改原数组,它只读取、只复制。哪怕你反复调用一百次,原数组的长度、元素值、引用地址全都不变。适合需要保留原始数据、又想快速提取子集的场景,比如日志切片、分页缓存、算法中间状态保存。
常见错误是以为它像 list.subList 那样返回视图——不是的,它返回的是全新堆内存上的独立数组。
参数顺序是 from(含)到 to(不含),越界会直接抛异常
from 必须 ≥ 0,to 必须 ≤ 原数组长度,且 from ≤ to。三者任一不满足,立刻抛 ArrayIndexOutOfBoundsException,不会静默截断或补空。
- 想取索引 2 到 5 的元素(共 3 个),写
copyOfRange(arr, 2, 5),不是6 - 想取最后两个元素,假设
arr.length == 10,就写copyOfRange(arr, 8, 10),别写9或11 - 空数组也能用:
copyOfRange(new int[0], 0, 0)返回空数组;但copyOfRange(new int[0], 0, 1)就炸
泛型擦除下,基本类型数组和引用类型数组行为一致
无论 int[]、String[] 还是 MyBean[],copyOfRange 的签名都是统一的:public static <t> T[] copyOfRange(T[] original, int from, int to)</t>。编译器靠类型推导自动补全泛型参数,不用手写 <string></string> 这类东西。
但要注意:对基本类型数组(如 int[]),它返回的仍是 int[],不是 Integer[];不存在自动装箱。如果你传入 int[] 却期望得到包装类数组,得自己遍历转换。
示例:
int[] src = {1, 2, 3, 4, 5};
int[] sub = Arrays.copyOfRange(src, 1, 4); // → {2, 3, 4}
性能上无拷贝优化,小数组快,大数组慎用
copyOfRange 底层调用 System.arraycopy,是 JVM 层面的高效内存复制,比手动 for 循环快。但它始终是 O(n) 时间 + O(n) 空间开销——你要截取 10MB 的字节数组中一段 1MB 子集,就得额外分配并复制这 1MB 内存。
如果只是临时读取、不需要持有副本,优先考虑用索引计算模拟“逻辑截取”,比如把 start 和 end 传给后续处理函数;真要新数组时,再调用 copyOfRange。
容易忽略的是:频繁调用它生成短生命周期数组,可能加剧 GC 压力,尤其在循环内——这时候该考虑复用缓冲区或改用 ByteBuffer.slice() 类方案。










