System.arraycopy 是 Java 中高效数组拷贝的底层方法,不新建对象、不触发 GC、直接内存拷贝,适用于高频大批量场景;需严格校验五参数边界,支持左闭右开区间截取与缓冲区复用优化。

System.arraycopy 是 Java 中真正能扛住高频、大批量数组截取的底层方法——它不新建对象、不触发 GC、直接内存拷贝,比 Arrays.copyOfRange() 更轻量,尤其适合对延迟或吞吐敏感的场景(比如实时日志解析、网络协议包处理、地理坐标批量筛选)。
核心用法:五参数必须对齐
调用格式固定为:System.arraycopy(src, srcPos, dest, destPos, length)
- src:源数组,不能为空,否则抛 NullPointerException
- srcPos:起始读取下标,必须 ≥ 0 且 ≤ src.length
- dest:目标数组,必须已 new 完成,不能为 null
- destPos:写入起始下标,必须 ≥ 0
-
length:要拷贝的元素个数,必须 ≥ 0,且满足:
srcPos + length ≤ src.length
destPos + length ≤ dest.length
任一条件不满足,运行时直接抛 ArrayIndexOutOfBoundsException —— 所以实际使用前建议先做边界校验,尤其 when from/to 来自用户输入或外部配置。
标准区间截取:封装成 subArray 工具方法
按 Java 通用习惯采用左闭右开区间 [from, to),例如截取索引 2 到 5(不含 5),即 3 个元素:
- 先计算长度:int len = to - from
- 创建目标数组:int[] result = new int[len]
- 执行拷贝:System.arraycopy(arr, from, result, 0, len)
完整示例:
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 + ")");
}
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 压力
如果同一源数组需反复截取不同位置,且最大截取长度已知(比如每次最多取 8KB 日志片段),可避免每次都 new 小数组:
- 预先分配一个足够大的缓冲数组,如 byte[] buffer = new byte[8192]
- 每次调用
System.arraycopy(src, offset, buffer, 0, actualLen) - 最后仅需 Arrays.copyOf(buffer, actualLen) 裁剪出真实结果
- 若后续只读不改,甚至可跳过 copyOf,仅传 buffer 和 actualLen 两个参数协作处理
这种模式在分片解析、流式解码等场景中能显著减少内存分配频率。
注意类型与语义边界
System.arraycopy 不做类型转换、不解析数据含义:
- 对 double[] 坐标数组,它只按元素个数拷贝,不会识别“每两个元素是一组经纬度”——业务层需自行算好 srcPos 和 length
- 对 LatLng[] 对象数组,拷贝的是引用,不是深拷贝;修改 result 中某个对象,原数组对应对象也会变
- 拼接两个数组时,第二段的 destPos 必须等于第一段长度,不能写 0 或 b.length,否则覆盖或越界
它只是高效搬运工,逻辑和安全得靠你来把关。


















