system.arraycopy位移本质是内存块复制覆盖,非真正移动;向右位移须从右往左拷贝防覆盖,向左位移则从左往右即可;重叠时jvm自动按安全顺序执行。

System.arraycopy 位移的本质是内存块拷贝
它不是“移动”而是“复制覆盖”,所以位移方向错了就会把还没读的数据提前覆盖掉。比如想把 arr[2] 到 arr[4] 往右挪 1 位,却从左往右复制,arr[2] 覆盖 arr[3] 后,原 arr[3] 就丢了。
关键判断:位移方向决定复制顺序——
- 向右位移(目标索引 > 源索引):必须从右往左复制,避免覆盖未读数据
- 向左位移(目标索引
- System.arraycopy 本身不判断方向,全靠你传的
srcPos和destPos控制
向右位移 3 个位置的正确写法
假设要把 arr[5]~arr[9](共 5 个元素)整体右移 3 位,即填入 arr[8]~arr[12]:
System.arraycopy(arr, 5, arr, 8, 5);
这里 srcPos=5,destPos=8,因为 8 > 5,JVM 内部会自动按从高下标到低下标的顺序执行拷贝(等价于倒序循环),确保 arr[9] 先拷到 arr[12],再拷 arr[8] → arr[11]……不会污染中间数据。
常见错例:System.arraycopy(arr, 5, arr, 6, 5) —— 看似只挪 1 位,但若数组长度不够、或起始重叠没算清,会越界或覆盖。
向左位移时最容易踩的边界坑
向左位移本质是“前段覆盖后段”,比如把 arr[3]~arr[7] 左移 2 位,目标是 arr[1]~arr[5]:
System.arraycopy(arr, 3, arr, 1, 5);
这时 destPos=1 ,JVM 自动正序拷贝,安全。
但极易出错的点:
-
destPos太小导致越界:比如destPos = -1直接抛ArrayIndexOutOfBoundsException - 源区间和目标区间重叠但长度算错:例如误传长度为
6,实际只挪了 5 个元素,多拷一个就可能读到脏数据 - 没预留空间:位移后新位置超出原数组长度,得自己扩容或截断,
System.arraycopy不管这个
和 for 循环比,快在哪?
不是语法糖快,是 JVM 对 System.arraycopy 做了深度优化:在满足条件时(如基本类型、连续内存、无 GC 引用检查需求),会直接调用 memmove 或 memcpy 等底层指令,一次搬运整块内存。而手动 for 循环每次都要做边界检查、数组访问、赋值三步,且无法被 JIT 彻底向量化。
不过要注意:如果数组元素是对象引用,且涉及跨代引用(比如从老年代拷到新生代),JVM 可能插入写屏障,性能优势会打折扣;纯 int/long 等基本类型才最稳。
真正容易被忽略的是:位移操作本身不改变数组长度,也不清理“空出来”的旧位置——那些索引上的旧值仍存在,GC 不会自动回收,如果它们是大对象引用,可能造成意外内存滞留。










