Java泛型数组不可直接创建,应以Object[]为底层数组,入口用set强校验类型、出口用get单元素转型;必要时通过Class反射生成真实类型数组,或优先使用泛型集合替代。

Java 中无法直接创建泛型数组,这是由类型擦除机制决定的硬性限制。想在泛型类中安全持有数组,关键不是“绕过擦除”,而是把类型安全控制在入口和出口——让编译期管住写入,运行时管住读出,中间用 Object[] 作为底层容器。
用 Object[] 作底层数组,入口强校验
声明成员时不写 T[],改用 Object[],避免在构造时就做不安全转型:
- 构造函数只初始化
new Object[size],不涉及任何泛型强制转换 -
set(int index, T item)方法接收T类型参数,编译器自动确保传入值符合泛型约束 - 内部直接存入
Object[],无需转型,无警告、无风险
读取时再做单元素转型,而非整数组转型
返回单个元素时,转型是安全且必要的:
-
get(int index)返回(T) array[index]—— 这个转型在运行时总能成功,因为写入时已保证类型正确 - 绝对不要提供
return (T[]) array这样的方法,它会暴露Object[]并引发ClassCastException - 如果真需要返回数组(如对外提供快照),应返回
Arrays.copyOf(array, size, T[]::new)或用反射生成正确类型的数组
必要时用反射创建真正泛型数组
当必须返回一个真实类型的数组(例如实现 Collection.toArray(T[]) 合约),使用 Array.newInstance:
- 需在构造时传入
Class类对象,比如GenericArray(5, String.class) - 初始化:
this.array = (T[]) Array.newInstance(componentType, size) - 这样生成的数组运行时类型就是
String[]等具体类型,可安全转型、可instanceof判断
优先考虑集合替代数组
除非有明确性能或接口契约要求(如 JNI、框架回调),否则更推荐用泛型集合:
-
private final List—— 无类型擦除隐患,API 更丰富list = new ArrayList(); - 若需数组语义(如固定长度、随机访问快),可用
list.toArray(new T[0])获取安全副本 - 集合天然支持协变读取(
? extends T)和逆变写入(? super T),灵活性远超数组










