bigywater.tech
Java 内部原理 · 118

Array.newInstance() 真实验证:反射创建的数组和普通数组真实是同一种运行时类型

泛型方法内部想写new T[size]会真实编译不过——这是系列前面反复验证过的泛型擦除的直接后果。这篇真实验证标准的绕过方式:java.lang.reflect.Array.newInstance(),以及它创建出来的数组到底是不是"真的"数组。

反射创建的数组真实类型完全一致
真实验证:Array.newInstance(int.class,5)创建的数组,getClass()真实和new int[5]返回完全相同的Class对象
异常行为真实和普通数组一致
真实验证:反射数组越界访问真实抛ArrayIndexOutOfBoundsException,负数长度真实抛NegativeArraySizeException,和普通数组毫无区别

上一篇:Object默认hashCode()真实验证

真实验证:动态创建基本类型和对象类型数组

用Class对象在运行时决定要创建什么类型的数组——这正是泛型方法内部no法直接new T[size]时的标准解法。

ArrayReflectNewInstanceDemo.java static <T> T[] createArray(Class<T> componentType, int size) { return (T[]) Array.newInstance(componentType, size); // 泛型方法内部无法直接 new T[size] }
真实实测
Array.newInstance(int.class, 5) 真实创建的类型: [I
真实设置intArray[0]=100后,读取: 100

真实创建的String[3]数组: [hello, null, null]
真实运行时类型: String[]

真实结果证明 Array.newInstance() 能在运行时才知道元素类型(通过 Class 对象)的情况下,动态创建出数组——这正是系列前面 泛型擦除那篇提到的限制的标准解决方案:泛型方法内部由于类型参数 T 在运行时已经被擦除,编译器不允许写 new T[size],但可以通过传入一个显式的 Class<T> 参数,用反射绕过这个限制。

真实验证:反射创建的数组和普通数组是完全同一种运行时类型

真实实测
反射创建的数组和普通数组真实是同一种运行时类型: true
不是"模拟"出来的数组,是完全一样的真实数组。这一行结果直接比较了 Array.newInstance(int.class, 5) 创建的数组和 new int[5] 创建的数组,两者的 getClass() 真实返回同一个 Class 对象——这证明反射创建数组这条路径,最终在 JVM 里生成的真实是和普通 new 语法完全等价的数组对象,不存在任何"反射版本"和"普通版本"的区别,后续对它做的任何操作(存取元素、传给其他方法、序列化等)真实表现完全一致。

真实验证:多维数组和异常行为

真实实测
真实创建的多维数组类型: [[I
真实多维数组维度: 2 x 3

反射数组越界访问真实抛出: ArrayIndexOutOfBoundsException
Array.newInstance(-1) 真实抛出: NegativeArraySizeException

真实结果验证了 Array.newInstance() 还有一个重载版本,能一次性传入维度数组直接创建多维数组;而涉及数组安全性的异常行为(越界访问、负数长度)真实和普通数组语法完全一致——反射这条路径完整复用了 JVM 底层数组机制的所有真实检查逻辑,没有走任何"捷径"绕过这些安全保障。

分步演示:反射数组是怎么被证明"不是模拟品"的

每一行都是真实运行这段代码得到的结果。

反射创建的数组和 new int[5] 真实是同一个 Class 对象;越界、负数长度的检查也和普通数组完全一致
这一步新验证的调用

    参考与说明

    • 本文全部结果均在本机真实运行 Java 17 得到,反射数组的类型一致性和异常行为重复运行完全一致。
    • 和泛型擦除那篇一起看,能理解Array.newInstance()是真实解决"擦除后无法用new T[]"这个语言限制的标准工具,而不是一个投机取巧的变通方案。
    • 没有涉及:List.toArray(T[])为什么需要传入一个数组参数而不是直接返回T[](结论同样和泛型擦除+运行时类型信息缺失有关)、Array.newInstance()在自定义序列化框架里动态重建对象数组的真实应用——这两个话题留给系列后面按需再写。
    京ICP备2026067502号-1京公网安备11010502063487号