System.arraycopy根据destPos与srcPos的大小关系自动选择拷贝方向:destPos>srcPos时倒序,destPos<srcPos时正序,destPos==srcPos时不搬运;参数非法(越界、类型不匹配、null)会提前抛异常,重叠本身安全。

System.arraycopy 在重叠区域拷贝时自动保证数据安全,不需要你手动判断方向或拆分逻辑——它内部会根据源起始位置(srcPos)和目标起始位置(destPos)的大小关系,动态选择正序或倒序复制,行为等价于 C 语言中的 memmove。
它怎么决定正着拷还是倒着拷?
关键看 destPos 和 srcPos 的相对位置:
- 如果 destPos > srcPos(目标起始在源起始右边),说明是“前向重叠”,JVM 自动从高索引往低索引倒序拷贝,避免还没读的数据被提前覆盖;
- 如果 destPos < srcPos(目标起始在源起始左边),属于“后向重叠”,则正序拷贝,同样不会丢数据;
- 如果 destPos == srcPos,就是原地复制,实际不搬运,或仅做长度校验后返回。
一个直观例子:数组内左移一位
对 int[] arr = {1,2,3,4,5} 执行:System.arraycopy(arr, 1, arr, 0, 3);
源区间是索引 1~3(元素 2、3、4),目标从 0 开始。因 destPos(0)< srcPos(1),属后向重叠,正序执行:
- 先拷
arr[1] → arr[0](2 覆盖 1) - 再拷
arr[2] → arr[1](3 覆盖 2) - 最后拷
arr[3] → arr[2](4 覆盖 3)
结果为 {2,3,4,4,5},正是预期的左移效果,全程无数据丢失。
真正要防的不是重叠,而是参数非法
重叠本身完全安全,出问题的根源永远是参数越界或类型不匹配:
-
srcPos + length > src.length或destPos + length > dest.length→ 抛ArrayIndexOutOfBoundsException - 源数组与目标数组类型不兼容(如 String[] 拷到 Integer[])→ 抛
ArrayStoreException - 任一数组为
null→ 抛NullPointerException
这些检查都在拷贝开始前完成,不会让错误写入悄悄发生。
别自己写循环模拟,那是自找麻烦
有人担心重叠危险,就先复制到临时数组再搬回来——这反而多一次内存分配和两次拷贝,拖慢性能,还浪费堆空间。System.arraycopy 的重叠处理是 JVM 级保障,比手写循环更可靠、更快(支持 SIMD 加速、无 Java 方法调用开销)。只要参数合法,结果一定语义正确。

















