System.arraycopy是Java中高效复制数组片段的native方法,不创建新对象、不触发GC,通过合理搭配新数组创建可实现分段截取;需严格校验参数避免越界异常,并注意类型安全与泛型限制。

System.arraycopy 是 Java 中高效复制数组片段的核心方法,不创建新对象、不触发 GC,适合对性能敏感的分段截取场景。它本身不“截取”数组,而是把源数组某一段内容,快速拷贝到目标数组指定位置——合理搭配新数组创建,就能实现真正意义上的分段截取。
明确参数含义,避免下标越界
调用格式:System.arraycopy(src, srcPos, dest, destPos, length)
- src:源数组(不能为空)
- srcPos:从源数组哪个索引开始读(≥0,且 ≤ src.length)
- dest:目标数组(必须已初始化,长度 ≥ destPos + length)
- destPos:往目标数组哪个索引开始写(≥0)
- length:要拷贝多少个元素(≥0,且 ≤ src.length − srcPos 且 ≤ dest.length − destPos)
任一参数违规都会抛 ArrayIndexOutOfBoundsException 或 NullPointerException。实战中建议先校验边界,尤其处理用户输入的起始/结束索引时。
实现任意区间截取(推荐封装成工具方法)
要从原数组 arr 截取 [from, to)(左闭右开,符合 Java 通用习惯),可这样写:
public static int[] subArray(int[] arr, int from, int to) {
if (arr == null) throw new IllegalArgumentException("源数组不能为null");
if (from < 0 || to > arr.length || from > to) {
throw new IndexOutOfBoundsException("索引越界: [" + from + ", " + to + ") 超出数组长度 " + arr.length);
}
int len = to - from;
int[] result = new int[len];
System.arraycopy(arr, from, result, 0, len);
return result;
}调用示例:subArray(new int[]{1,2,3,4,5}, 1, 4) → 返回 {2,3,4}。
高效处理大数组或频繁截取场景
如果需多次从同一源数组不同位置截取,且每次结果数组大小已知,可复用目标数组减少 GC 压力:
- 预先分配一个足够大的缓冲数组(如最大可能截取长度)
- 每次调用
arraycopy时复用该缓冲区,再用Arrays.copyOf按需裁剪(仅最后一步新建小数组) - 若后续直接使用截取结果做只读操作,甚至可跳过裁剪,仅维护有效长度变量
例如日志行解析、网络包分片等场景,这种模式能显著降低内存分配频率。
注意类型安全与泛型限制
System.arraycopy 是 native 方法,不进行运行时类型检查。若源数组和目标数组类型不兼容(如把 String[] 拷到 Integer[]),会在运行时抛 ArrayStoreException。
- 基本类型数组之间不可互拷(
int[]不能拷到long[]) - 引用类型数组要求目标数组的组件类型是源数组组件类型的父类或接口(协变规则)
- 泛型数组受限于类型擦除,无法直接用于
List<T>[]等结构,此时建议改用Stream或手动循环

















