Java System.arraycopy出现ArrayStoreException怎么排查

作者:技术拾光

时间:2026-07-21

浏览:330

System.arraycopy抛出ArrayStoreException源于目标数组组件类型与源数组元素实际类型不匹配,常见于泛型擦除后Object[]复制到String[]或基本类型数组误用。可通过检查运行时类型、打印组件类型或循环校验元素类型定位问题。

文章目录

你在使用System.arraycopy时遇到了ArrayStoreException?这其实是Java在运行时帮你做的一次类型安全检查,只不过它直接拒绝了你的操作。简单来说,就是System.arraycopy在执行复制时,发现源数组里的某个元素类型跟目标数组的组件类型不匹配,于是果断抛出了异常。

Java System.arraycopy出现ArrayStoreException怎么排查

问题出在哪里?核心就一句话:目标数组期望接收的元素类型,和源数组里实际装着的元素类型,对不上号。下面我们拆开来看,怎么一步步定位并解决。

确认源数组和目标数组的组件类型是否兼容

这是最常见的原因。目标数组声明为String[],但源数组里却藏着一个Integer对象——Java数组虽然是协变的,但System.arraycopy在运行时会逐一检查每个元素,一旦发现类型不匹配,直接抛出异常。

  • 检查源数组的声明类型和目标数组的声明类型。比如源数组声明为Object[] src = new Integer[3];,目标数组是String[] dst = new String[3];,这俩一碰就炸。
  • 即便源数组里实际存的都是String对象,但如果它的编译时类型是Object[],而目标数组是String[],复制时依然可能失败。关键看运行时目标数组的组件类型能否接受源元素的实际类型——JVM可不会因为“看起来都是String”就网开一面。
  • 一个典型例子:Object[] src = {new Integer(1)}; String[] dst = new String[1]; System.arraycopy(src, 0, dst, 0, 1); → 直接抛出ArrayStoreException,因为Integer塞不进String[]。

注意泛型擦除与 Object[] 的陷阱

从集合转数组时,这个坑特别容易踩。比如list.toArray()返回的是Object[],你直接把它往String[]里复制,JVM在运行时当然要较真——它会逐个检查每个元素是不是String。

  • 错误写法:String[] arr = new String[list.size()]; System.arraycopy(list.toArray(), 0, arr, 0, list.size()); 这行代码大概率会抛出异常,因为list.toArray()返回的数组运行时类型是Object[],不是String[]。
  • 正确做法:用带参数的toArray(T[])方法,比如String[] arr = list.toArray(new String[0]);,它返回的就是真正的String[]类型数组,复制时自然安全。
  • 如果非要用arraycopy,那就得确保源数组的运行时类型和目标数组一致。可以先通过Arrays.copyOf做一次安全转型,或者显式进行类型转换(前提是你能保证所有元素都是目标类型)。

检查是否误用了基本类型数组与引用类型数组

这里有个关键点:ArrayStoreException只发生在引用类型数组之间。如果你看到这个异常,那至少有一个参数是引用类型数组(比如String[]、Integer[]),绝对不会是int[]、double[]这类基本类型数组。

  • 基本类型数组之间复制,不会抛出ArrayStoreException(但可能因为数组长度不够抛出ArrayIndexOutOfBoundsException,或者类型不匹配导致静默截断)。
  • 混合使用时尤其要小心:把Integer[]复制到Number[]是合法的,因为Integer是Number的子类;但复制到String[]就非法了。
  • 可以用src.getClass().getComponentType()和dst.getClass().getComponentType()打印出实际组件类型,对比一下就知道问题出在哪。

调试建议:快速定位问题元素

异常堆栈通常不会告诉你具体是第几个元素出了问题,不过我们可以手动模拟校验逻辑,快速缩小范围。

  • 在调用arraycopy之前,加一层循环逐个检查:for (int i = 0; i < length; i++) { if (!dst.getClass().getComponentType().isInstance(src[i])) { ... } },这样就能精确定位到出问题的元素。
  • 或者用IDE的调试模式,在异常抛出前暂停,观察src[i]的实际类型以及dst的组件类型。
  • 日志中打印src.getClass().getName()和dst.getClass().getName(),比如[Ljava.lang.String;表示String[],[Ljava.lang.Object;表示Object[],一目了然。

实用工具推荐

电子包浆

绿化、压缩、噪点和虚拟水印,自由调节做旧程度。

使用 ›
图片压缩

选择画质和输出格式,预览压缩前后的大小。

使用 ›
相关文章