system.arraycopy是jvm内存块搬运指令,非普通复制方法;它通过跳过java字节码循环和逐元素检查实现高效,但参数任一错误即抛异常,调用格式固定为system.arraycopy(src, srcpos, dest, destpos, length),顺序与含义不可混淆。

System.arraycopy 不是普通复制方法,而是 JVM 层面的内存块搬运指令。它快,是因为跳过 Java 字节码循环和逐元素检查;它严,是因为参数错一个就立刻抛异常——没有静默失败,全靠你写对。
五个参数必须逐个对齐
调用格式固定为:System.arraycopy(src, srcPos, dest, destPos, length),顺序不能换,含义不能混:
- src:源数组,不能为空,否则直接抛 NullPointerException
- srcPos:从源数组第几个索引开始读,必须 ≥ 0 且 ≤ src.length;若 srcPos + length 超出范围,运行时抛 ArrayIndexOutOfBoundsException
- dest:目标数组,必须已 new 出来、非 null,且组件类型与 src 兼容(如 String[] 可拷到 Object[],但 Integer[] 不可接收 int[])
- destPos:往目标数组第几个索引开始写,必须 ≥ 0,且 destPos + length ≤ dest.length
- length:拷多少个元素,可以为 0(合法空操作,常用于边界预检),但不能为负(否则抛 NegativeArraySizeException)
截取与拼接:算准起始和长度
它本身不“截取”,但配合新数组创建,就能高效实现任意区间提取:
- 左闭右开区间 [from, to) 对应:srcPos = from,length = to − from,dest 长度至少为 length
- 例如从 int[] arr 截取索引 2 到 5(含 2、3、4),写法是:System.arraycopy(arr, 2, result, 0, 3)
- 拼接两个数组 a 和 b:先 new 总长数组 result,再分两步搬运——arraycopy(a, 0, result, 0, a.length),然后 arraycopy(b, 0, result, a.length, b.length);第二步的 destPos 必须是 a.length,写成 0 就会覆盖
原地移位:JVM 自动选方向,你只管传对参数
当 src == dest,就是内存重排。JVM 根据 srcPos 和 destPos 大小关系自动决定正向或倒序搬运,避免数据覆盖:
- 左移(destPos :如把 arr[4..8] 前移到 arr[2..6],写 System.arraycopy(arr, 4, arr, 2, 5),JVM 正向执行
- 右移(destPos > srcPos):如把 arr[2..6] 后移到 arr[5..9],写 System.arraycopy(arr, 2, arr, 5, 5),JVM 倒序搬运,先处理高位
- 不需要手动判断方向再 if-else 分支——传对参数,JVM 自己选策略
性能真正快的条件
它不是万能加速器,提速依赖具体场景:
- 基本类型数组(int[]、byte[] 等) 拷贝长度 ≥ 256 时优势明显,JVM 可启用 SIMD 指令批量搬运
- 对象数组(String[]、MyBean[]) 也快,只复制引用,不触发 GC 写屏障
- length ≤ 16 的小数组,for 循环往往更快——JNI 调用开销盖过了搬运收益
- 目标数组必须已预分配:Arrays.copyOf 会 new 新数组,clone() 无法指定范围,而 arraycopy 是唯一零分配选择
- 避免在循环体内频繁调用,参数尽量用编译期可判定的常量,利于 JIT 内联优化
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











