Java数组拷贝无统一类型检查流程,System.arraycopy运行时强检、Arrays.copyOf编译期+运行时双重约束、clone()仅容器级匹配、for循环全由开发者负责。

Java 数组拷贝本身没有统一的“类型检查流程”,但不同拷贝方式会在不同阶段触发 JVM 的类型校验——有的在编译期约束,有的在运行时强检,有的甚至不检查。关键不是“有没有检查”,而是“谁来检、何时检、出错时怎么表现”。
System.arraycopy:运行时强类型校验
这是最严格、最典型的类型检查场景,发生在 native 层调用前,由 JVM 主动执行:
- 源数组与目标数组必须是同一维度的同种引用类型(如 String[] → String[]),或兼容的基本类型数组(int[] → int[] 合法,int[] → long[] 直接抛 ArrayStoreException)
- 对引用类型数组,校验发生在每个元素赋值瞬间:若 src[i] 实际不是 dest 声明类型的实例(比如把 Integer 写入 String[]),就在第 i 步抛 ArrayStoreException,不会提前拒绝
- 基本类型数组之间不兼容(如 byte[] 拷到 int[])会立即抛 ArrayStoreException,不尝试自动转换
- 边界检查(如 srcPos + length ≤ src.length)优先于类型检查;不满足则直接抛 ArrayIndexOutOfBoundsException
Arrays.copyOf:编译期 + 运行时双重保障
该方法本质是先 new 新数组,再调用 System.arraycopy,因此继承其全部运行时校验逻辑,但多一层编译期泛型桥接:
- 方法签名 <T> T[] copyOf(T[] original, int newLength) 由 javac 强制约束传入类型,避免原始类型误用(如传入 int 而非 int[])
- 运行时仍依赖 System.arraycopy 完成搬运,最终类型安全由后者兜底
- 当 newLength > original.length 时,新增位置用默认值填充(0 或 null),不触发类型问题
clone():仅容器级匹配,无逐元素校验
Object.clone() 对数组有特殊支持,但校验非常轻量:
- 返回数组类型与原数组完全一致(String[].clone() 返回 String[],不能直接赋给 Object[] 变量而不显式转型)
- 不检查元素内容是否合法——若原 Object[] 中混入了非 String 实例,克隆后依然存在;后续写入目标 String[] 才会报错
- 对基本类型数组,clone 是纯值拷贝,无引用类型校验负担
for 循环:无 JVM 校验,全由开发者控制
这是纯 Java 层实现,JVM 不介入任何类型检查:
- 基本类型循环赋值:编译器在赋值语句处做隐式转换检查(如 int → short 需显式强转,否则编译失败)
- 引用类型循环赋值:仅检查变量声明类型是否兼容(如 Object o = arr[i] 总是合法;但 String s = arr[i] 若 arr 是 Object[],则可能运行时报 ClassCastException)
- 数组协变带来的风险在此完全暴露:Object[] 可以接收 String[],但往里写 Integer 就会出错,而 for 循环本身不拦

















