System.arraycopy不创建新数组,需预分配目标数组并精确控制起始位置与长度,适用于高性能切片与数据迁移;Arrays.copyOf则自动创建新数组,适合简单扩容或截断。

System.arraycopy 不是“切片函数”,也不自动分配新数组,但它能以接近内存拷贝的速度完成精准的数组内容提取与迁移——关键在于你提前准备好目标容器,并精确控制起始位置和长度。
切片:把一段数据高效抽出来存进已有数组
所谓“切片”,本质是从源数组中截取连续子序列,写入另一个已分配好的数组。它不生成新数组,所以必须手动 new 出目标数组:
- 想取
int[] src = {10,20,30,40,50}的中间三个数(20,30,40),存到新数组开头:
int[] slice = new int[3];<br>System.arraycopy(src, 1, slice, 0, 3);
结果:slice = [20, 30, 40] - 若要存到目标数组偏移位置(比如第2位开始),只需改
destPos:
int[] buf = new int[10];<br>System.arraycopy(src, 1, buf, 2, 3);
结果:buf = [0, 0, 20, 30, 40, 0, 0, 0, 0, 0] - 注意:不能用
src.length当作 length 参数来“全量切片”——必须显式指定你要多少个元素,且确保srcPos + length ≤ src.length
数据迁移:复用缓冲区,避免重复分配
在 IO、编解码、消息解析等场景中,频繁创建数组会加重 GC 压力。用 arraycopy 迁移数据到预分配的 buffer,是典型的高性能做法:
- 网络收到一个
byte[] packet,只想把其中 header 后的 payload(比如索引 12 开始的 1024 字节)搬进固定缓存byte[] payloadBuf:System.arraycopy(packet, 12, payloadBuf, 0, 1024); - 同一块内存多次复用:解密结果写入
buf偏移 0,校验后把有效载荷再拷到偏移 1024 处压缩,全程不 new 新数组 - 优势明显:跳过对象分配、GC 记录、初始化零值等开销;JVM 可直接调用
memmove级指令
跨数组迁移时必须检查的三件事
参数错一个,运行就抛异常,没有容错:
-
非空校验:src 和 dest 都不能为
null,否则NullPointerException -
越界防护:必须同时满足
srcPos ≥ 0且srcPos + length ≤ src.lengthdestPos ≥ 0且destPos + length ≤ dest.length -
类型兼容:int[] → long[] 不行,String[] → Object[] 可以,但 int[] → Integer[] 会触发
ArrayStoreException
和 Arrays.copyOf 的本质区别
别为了省一行代码误用 Arrays.copyOf(src, len) 做“切片”:
-
Arrays.copyOf内部就是先new数组,再调arraycopy——如果你已有目标数组,它多一次分配,纯属浪费 - 真正需要“新数组+切片”时,才用
Arrays.copyOfRange(src, from, to),它语义清晰、安全封装 -
arraycopy的价值,恰恰在你**已有目标容器**的前提下,实现零分配的数据落位


















