system.arraycopy 比 for 循环快因其是 jvm 内置 native 方法,直接内存操作,避免字节码开销;但仅浅拷贝,需预分配足够长度的目标数组且类型兼容。

System.arraycopy 为什么比 for 循环快
因为 System.arraycopy 是 JVM 内置的本地方法(native),底层直接操作内存地址,跳过了 Java 字节码的逐元素访问开销。for 循环拷贝则要经过边界检查、数组读写、循环控制等多层字节码指令,尤其在大数组场景下性能差距明显(实测常达 2–5 倍)。
但注意:它只做浅拷贝,不处理对象内部引用;且不会自动扩容目标数组——目标数组必须已存在且足够长,否则抛 ArrayStoreException 或 IndexOutOfBoundsException。
调用时五个参数怎么填才不出错
签名是 System.arraycopy(Object src, int srcPos, Object dest, int destPos, int length),最容易错的是位置和长度的组合逻辑:
-
srcPos和destPos是起始索引(从 0 开始),不是偏移字节数 -
length是要拷贝的元素个数,不是目标数组长度 - 必须满足:
srcPos + length ≤ src.length且destPos + length ≤ dest.length,否则运行时报IndexOutOfBoundsException - 源数组和目标数组类型必须兼容(如
String[]→Object[]合法,但int[]→Integer[]会报ArrayStoreException)
示例:把 int[] src = {1,2,3,4,5} 的后三个元素拷到 int[] dst = new int[10] 的索引 2 开始处:System.arraycopy(src, 2, dst, 2, 3) → dst 变成 {0,0,3,4,5,0,0,0,0,0}。
基本类型数组和引用类型数组有区别吗
没有本质区别——System.arraycopy 对所有数组类型一视同仁,都是按内存块复制(即“位拷贝”)。但语义后果不同:
- 基本类型(
int[]、double[]等):拷贝的是真实数值,源目标完全独立 - 引用类型(
String[]、MyObj[]等):拷贝的是引用地址,源和目标数组中对应位置指向同一个对象实例
也就是说,修改目标数组中某个 String 元素本身不可变,但若元素是可变对象(如 ArrayList),改它的内容会影响源数组看到的状态。这不是 System.arraycopy 的问题,而是浅拷贝的固有行为。
替代方案对比:Arrays.copyOf vs clone() vs System.arraycopy
三者适用场景不同,别为了“看起来简洁”而误用:
-
Arrays.copyOf(src, newLength):本质是先新建数组再调arraycopy,适合需要改变长度的场景;但若目标数组已存在且长度匹配,它多一次分配,纯属浪费 -
arr.clone():返回新数组,语义清晰,但无法指定拷贝范围(只能全量),也不能指定目标位置;且对多维数组只克隆第一层 -
System.arraycopy:唯一支持“部分拷贝 + 指定目标偏移 + 复用已有数组”的方案,也是 JVM 层面最轻量的物理拷贝入口
真正要注意的细节是:目标数组必须预先创建好,且长度不能靠猜——比如想把 1000 个元素从位置 100 拷到另一个数组的开头,目标数组至少要 new int[1000],而不是 new int[src.length]。










