system.arraycopy是java性能最优的数组拷贝底层方案,需严格填写五个参数并满足边界条件,仅支持浅拷贝且类型必须兼容,适用于已有目标数组或需偏移拷贝的场景。

Java数组拷贝不是“复制一下就行”,关键在选对方法、填准参数、避开类型雷区。System.arraycopy 是性能最优的底层方案,但不自动建数组、不智能容错,用对了快如闪电,填错一个参数立刻崩溃。
五个参数怎么填才不越界
签名是 System.arraycopy(Object src, int srcPos, Object dest, int destPos, int length),每个参数都必须严格满足边界条件:
- src 和 dest 都不能为 null,否则抛 NullPointerException
- srcPos ≥ 0 且 srcPos + length ≤ src.length(不是只看 length ≤ src.length)
- destPos ≥ 0 且 destPos + length ≤ dest.length
- length ≥ 0;等于 0 是合法操作,不报错也不搬运
例如:想从 int[] src = {1,2,3,4,5} 中取下标 2~4(即元素 3、4、5),应写 System.arraycopy(src, 2, dest, 0, 3)。若误写成 length=4,即使 dest 足够长,也会因 2+4 > 5 报 ArrayIndexOutOfBoundsException。
截取、拼接、原地移动全靠它
arraycopy 本身不做“创建新数组”动作,但配合 new 操作就能实现常见需求:
-
截取子区间:先算长度(如
to - from),new 目标数组,再搬运。例如subArray(arr, 1, 4)→ 拷贝 arr[1] 到 arr[3] 共 3 个元素 -
两个数组拼接:目标数组长度 = a.length + b.length;第一段写入位置是 0,第二段起始位置必须是
a.length,否则会覆盖 - 原地移动(如左移/右移):当 src == dest 时,JVM 自动判断搬运方向——srcPos
类型兼容性是硬约束,不是编译期警告
它不做运行时类型转换,只做内存块搬运,因此组件类型必须兼容:
- 基本类型数组之间互不兼容:int[] 不能拷到 long[],哪怕长度匹配也抛 ArrayStoreException
- 引用类型遵循赋值规则:String[] 可拷到 Object[](子类→父类),但 Object[] 拷到 String[] 会失败
- 泛型擦除不影响判断:List
[] 可安全拷到 Object[],因为运行时仍是对象数组
注意:无论基本类型还是引用类型,arraycopy 都只做浅拷贝。拷 String[] 时复制的是引用地址,不是字符串内容;拷自定义对象数组时,新旧数组里同一索引指向同一个对象实例。
别用它替代 Arrays.copyOf,也别用 for 循环硬刚
明确适用场景,才能发挥最大价值:
- 已有目标数组(如缓冲区复用、帧处理循环)→ 用 arraycopy,零额外 GC 开销
- 需要从中间开始拷、或只拷一段 → 只能用 arraycopy,copyOf 和 copyOfRange 都不支持偏移源起点
- 只想快速得到一个新数组副本 → 优先用 Arrays.copyOf 或 copyOfRange,语义清晰、不易出错
- 千万别手写 for 循环模拟拷贝:性能差一个数量级,还容易漏边界、写错下标
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











