Java禁止new T[10]因类型擦除致运行时无法校验数组元素类型,安全起见编译器直接禁止;推荐用Class<T>配合Array.newInstance动态创建,或优先使用ArrayList等泛型集合。

Java 中不能直接写 T[] arr = new T[10],不是语法疏漏,而是类型擦除与数组运行时类型检查机制冲突所致。T 在运行时不存在,JVM 无法确认该数组该接受什么类型元素,也就无法执行 ArrayStoreException 这类安全校验。所以编译器主动禁止,不是“暂时不支持”,而是设计上的必要限制。
用 Class 配合 Array.newInstance 动态创建
这是最贴近“真正泛型数组”语义的方案——不是绕过擦除,而是补全缺失的运行时类型信息。
- 方法签名必须显式接收
Class<t></t>参数,例如:public <T> T[] createArray(Class<T> clazz, int length) - 内部调用
Array.newInstance(clazz, length),返回Object,再强制转型为T[] - 调用时传具体引用类型的 Class 对象,如
String.class、Integer.class;不可用int.class(它生成的是int[],不是泛型数组) - 在泛型容器类中,建议把
Class<E>缓存为字段,避免每次扩容都重复反射调用
用 Object[] + 强制转型(谨慎使用)
这是最简但风险最高的方式,适用于工具类或框架内部,且能严格控制数组访问边界。
- 声明为
Object[],再转型:@SuppressWarnings("unchecked") T[] arr = (T[]) new Object[10] - 转型本身不抛异常,但若后续误存非 T 类型对象,会在取出时才触发
ClassCastException(延迟失败) - 仅当明确知道所有写入操作都受控时才考虑,不推荐在业务逻辑中裸用
优先选用 ArrayList 等泛型集合
绝大多数场景下,这才是真正合理、安全、简洁的解法。
立即学习“Java免费学习笔记(深入)”;
-
ArrayList<T>内部用Object[]存储,但通过泛型约束和封装 API 消除了手动管理容量和类型转换的负担 - 自动扩容、线程安全封装(
Collections.synchronizedList)、丰富操作接口,远超原生数组能力 - 只有在需要连续内存布局、JNI 交互、或对接 Netty/ByteBuffer 等底层框架时,才有必要回归数组
避免常见错误写法
有些看似可行的写法实际埋下隐患,需特别注意:
-
List<String>[] arr = (List<String>[]) new List[10]:虽能编译,但属于原始类型数组转型,JVM 无法阻止你往里塞List<Integer>,导致堆污染 -
new T[5]在类字段初始化中直接出现:编译报错,且没有运行时上下文补全类型,完全不可行 - 试图用嵌套泛型类型获取 Class,如
List<String>.class:实际得到的是List.class,泛型参数已丢失,无法构造正确数组


















