system.arraycopy 是 jvm 层内存块搬运指令,参数严格校验、缺一不可:src 和 dest 非空且类型兼容,srcpos/destpos 与 length 满足边界约束,越界或类型不匹配时运行时立即抛异常。

System.arraycopy 不是“复制函数”,而是 JVM 层面的内存块搬运指令。它快,是因为跳过 Java 层循环和逐元素校验;它严,是因为参数错一个,运行时立刻抛异常——没有警告,不静默修复,全靠你写对。
参数含义必须逐个对齐
调用格式固定:System.arraycopy(src, srcPos, dest, destPos, length),五个参数缺一不可,各自承担明确职责:
-
src:源数组,不能为空,否则直接抛
NullPointerException -
srcPos:从源数组第几个索引开始读,必须 ≥ 0,且
srcPos + length ≤ src.length -
dest:目标数组,必须已
new出来,不能为空,且组件类型需兼容(如String[]可往Object[]拷,但反过来不行) -
destPos:往目标数组第几个索引开始写,必须 ≥ 0,且
destPos + length ≤ dest.length -
length:要拷贝的元素个数,可以为 0(合法空操作,用于边界预检),但不能为负(否则抛
NegativeArraySizeException)
常见越界报错与快速定位方法
绝大多数 ArrayIndexOutOfBoundsException 来自两个硬约束未同时满足:
- 源侧越界:
srcPos + length > src.length - 目标侧越界:
destPos + length > dest.length
调试建议:
- 把参数单独提取为变量并打印:
System.out.printf("src.len=%d, srcPos=%d, len=%d → max=%d%n", src.length, srcPos, length, srcPos + length); - 关键路径加断言或校验:
if (length > src.length - srcPos || length > dest.length - destPos) throw new IllegalArgumentException(...); - 避免硬编码长度,改用
Math.min(src.length - srcPos, dest.length - destPos)控制安全拷贝量
同数组原地移位:方向由参数隐式决定
当 src == dest,就是内存重排。JVM 自动根据 srcPos 和 destPos 大小关系选择正向或倒序搬运,防止覆盖:
- 左移(destPos :如
arraycopy(arr, 4, arr, 2, 5),JVM 正向执行,安全 -
右移(destPos > srcPos):如
arraycopy(arr, 2, arr, 5, 5),JVM 倒序执行,先搬高位再覆盖低位 -
destPos == srcPos 且
length ≠ 0:等效空操作;length == 0则只做完整参数校验,可作轻量预检
类型不匹配与空引用:运行时才暴露的问题
编译器不检查类型兼容性,真正校验发生在 JVM 执行时:
-
ArrayStoreException:源数组组件类型无法赋值给目标数组组件类型,例如int[] → long[]、Object[] → String[] -
NullPointerException:src或dest为null,和数组内元素为null无关
预防措施:
- 调用前显式判空:
if (src == null || dest == null) throw ... - 避免跨大类赋值,基本类型数组之间严格区分,引用类型遵循继承关系
- 若需泛型安全,优先考虑
Arrays.copyOf或封装工具类做类型适配
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











