system.arraycopy是jvm内存搬运原语,非复制函数;其五个参数(src、srcpos、dest、destpos、length)顺序固定、各司其职,任一违规即抛nullpointerexception、arrayindexoutofboundsexception或arraystoreexception,不静默修复。

System.arraycopy 不是“复制函数”,而是 JVM 层面的内存搬运原语,参数填错一个,运行时立刻崩溃,不沉默、不妥协。
五个参数各司其职,顺序不能颠倒
签名是 System.arraycopy(Object src, int srcPos, Object dest, int destPos, int length),每个参数含义明确且不可替代:
-
src:源数组对象,必须非 null;为 null 直接抛
NullPointerException -
srcPos:从源数组第几个索引开始读,必须 ≥ 0,且
srcPos + length ≤ src.length,否则越界 - dest:目标数组对象,必须已分配、非 null;类型需兼容(如 String[] → Object[] 合法,反之非法)
-
destPos:往目标数组第几个索引开始写,必须 ≥ 0,且
destPos + length ≤ dest.length - length:要拷贝的元素个数,不是结束下标;为 0 合法,不搬运但完成全部校验
越界和类型错误,全在运行时爆发
它不做编译期类型推断,所有检查都延迟到执行瞬间——这是高效的前提,也是出错的代价:
Java JDK 25 来自 OpenJDK 官方归档,版本为 JDK 25,本条下载地址已指向官方 Windows x64 zip 安装包直链,适合调试旧项目或兼容旧版 Java 运行环境。
- 索引超限(如
srcPos + length > src.length)→ 立即抛ArrayIndexOutOfBoundsException - 类型不匹配(如把
Object[]往String[]拷)→ 抛ArrayStoreException,已拷部分不回滚 - 负数 length 或负索引 →
NegativeArraySizeException或IndexOutOfBoundsException - 推荐做法:关键路径前用
Math.min()截断 length,或封装带预检的工具方法
同一数组内移动,方向由参数自动决定
当 src == dest,JVM 内部按 srcPos 和 destPos 关系智能选序,无需手写分支逻辑:
- 左移(destPos :如
arraycopy(arr, 4, arr, 2, 5),正向搬,安全覆盖 -
右移(destPos > srcPos):如
arraycopy(arr, 2, arr, 5, 5),倒序搬,防数据丢失 -
重叠区间合法,但必须满足边界约束:
srcPos + length ≤ arr.length且destPos + length ≤ arr.length - 误判方向再 if-else 分支,反而引入 bug;传对参数,JVM 自己搞定
基本类型与引用类型,行为本质不同
arraycopy 不懂业务语义,只做内存块复制——效果差异完全取决于数组元素类型:
- int[]、byte[] 等基本类型数组:值拷贝,源与目标彻底隔离;改一方不影响另一方
- String[]、Person[] 等引用类型数组:浅拷贝,只复制引用地址;两个数组指向同一堆对象
- String 因不可变显得“安全”,但 Person 类若含 public 字段,改
dst[0].age就会同步影响src[0].age - 需深拷贝?必须手动遍历 + clone() 或构造新对象,arraycopy 不提供该能力
小数组慎用,大数组才见真章
它的性能优势有门槛,并非“用了就快”:
- 长度 ≤ 4 的数组,JNI 调用开销常高于简单赋值;≤16 时 for 循环可能更快
- 基本类型数组 ≥ 256 元素,JVM 可启用 SIMD 指令批量搬运,提速显著
- 对象数组也快,但仅因跳过 GC 写屏障,不触发对象创建或回收压力
- 避免在循环体内反复调用 arraycopy 处理极小片段;合并成一次大拷贝更高效
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










