system.arraycopy做数组切片本质是精准内存搬运,需手动预分配目标数组、确保类型兼容、严格校验五参数边界,否则抛arrayindexoutofboundsexception或arraystoreexception。

用 System.arraycopy 做数组切片,核心不是“创建新片”,而是“精准搬运一段内存”。它不自动分配目标数组、不检查业务逻辑,只做高效位拷贝——所以快,但也容易出错。关键在参数对齐和预分配。
切片前必须自己分配目标数组
它不会帮你 new 数组,目标数组得提前准备好,长度必须等于你要截取的元素个数:
- 想取
arr[2]到arr[5](含头不含尾,共 3 个元素),目标数组就得是new int[3] - 类型必须兼容:
int[]只能拷到int[];String[]可以拷到Object[],但反过来不行 - 写错长度会直接抛
ArrayIndexOutOfBoundsException或ArrayStoreException,没有容错
标准切片写法:五参数严丝合缝
签名是 System.arraycopy(src, srcPos, dest, destPos, length),切片时通常固定为:
-
srcPos = 起始索引(比如从第 2 个元素开始,就填2) -
length = 结束索引 - 起始索引(如截[2,5),长度就是5-2=3) -
destPos = 0(新数组从头填,最常用) -
dest必须是非 null 且长度 ≥length
示例:subArray(new int[]{1,2,3,4,5}, 1, 4) → 搬 arr[1] 开始的 3 个元素到新数组索引 0 起:System.arraycopy(arr, 1, result, 0, 3),结果是 {2,3,4}。
高频优化:复用缓冲区减少 GC
如果频繁切片同一类数据(如日志解析、网络包拆帧),别每次都 new 小数组:
- 预分配一个足够大的缓冲数组(例如最大切片长度为 8192,就建
byte[8192]) - 每次调用
arraycopy往这个缓冲区里拷,起始位置可变 - 最后用
Arrays.copyOf(buffer, actualLen)截出真实结果——只在最终一步分配小对象 - 若后续只读,甚至可跳过
copyOf,只维护一个validLength变量标记有效范围
切片时最容易踩的三个坑
不是功能问题,全是参数组合越界:
-
srcPos + length > src.length:比如数组长 5,却从索引 3 搬 3 个 →3+3=6 > 5,立刻报错 -
destPos + length > dest.length:目标数组长度 3,却往索引 1 搬 3 个 →1+3=4 > 3,也报错 - 类型擦除陷阱:泛型数组如
List<string>[]</string>拷到Object[]合法,但若目标是String[]就会运行时报ArrayStoreException











