System.arraycopy本身不校验参数,必须由调用方手动验证三项条件:srcPos≥0且srcPos+length≤src.length、destPos≥0且destPos+length≤dest.length、length≥0;否则立即抛ArrayIndexOutOfBoundsException或NullPointerException。

System.arraycopy 本身不做参数验证,它只在 JVM 底层执行内存块搬运,所有边界检查必须由调用方手动完成。一旦参数违法,立刻抛出 ArrayIndexOutOfBoundsException 或 NullPointerException,没有容错、不静默截断、也不提示具体哪项越界。
必须手动校验的三项核心条件
调用前需同时满足以下全部,缺一不可:
- 源数组安全:srcPos ≥ 0 且 srcPos + length ≤ src.length
- 目标数组安全:destPos ≥ 0 且 destPos + length ≤ dest.length
- 长度合法:length ≥ 0(length == 0 是合法空操作,可用于预检)
容易被忽略的隐性风险
这些不是“边界计算错误”,而是逻辑层面的疏漏:
-
null 引用未判:src 或 dest 为 null 会直接抛
NullPointerException,常被误认为是越界 - 动态索引未同步重算:如 srcPos = i * 2,则校验必须用 i * 2 + length ≤ src.length,不能只验 i
- length 含义混淆:length 是“拷贝元素个数”,不是“目标结束下标”;destPos + length 才是写入区域上限
- 数组重建后未更新 length:源数组被截断或替换后,仍沿用旧 length 值,必然越界
推荐的安全封装方式
把重复校验收口到一个工具方法,兼顾性能与可维护性:
public static <T> void safeArrayCopy(T[] src, int srcPos, T[] dest, int destPos, int length) {if (src == null || dest == null) throw new NullPointerException();
if (srcPos < 0 || destPos < 0 || length < 0)
throw new IndexOutOfBoundsException();
if (srcPos + length > src.length || destPos + length > dest.length)
throw new IndexOutOfBoundsException("copy would exceed array bounds");
System.arraycopy(src, srcPos, dest, destPos, length);
}
什么时候不该用 arraycopy
如果你的需求本质是“按需新建+拷贝”,而不是往已有数组里填数据,就该换用更合适的工具:
- 用
Arrays.copyOf(src, newLength):自动分配新数组、处理扩容/截断、内部已做完整校验 - 用
Arrays.copyOfRange(src, from, to):语义清晰,直接表达“截取区间”,避免手算 offset 和 length - 当目标容量不确定、或仅需浅拷贝整个数组时,它们比裸写 arraycopy 更安全简洁

















