在 Java 中不能直接创建泛型数组(如 new T[]、new List<String>[]),这是 Java 泛型设计中的一个刻意限制,主要原因在于 类型擦除(Type Erasure) 和 数组的运行时类型安全机制 之间的冲突。
下面分点说明原因和背后的设计逻辑。
Java 的泛型是编译期特性:
List<String> list = new ArrayList<>();
在运行时,实际类型是:
List // 没有 String 信息
这意味着:
List<String>[] 和 List<Integer>[] 在运行时无法区分数组是** covariant(协变)** 的,并且会在运行时进行类型检查:
Object[] objs = new String[10];
objs[0] = 123; // 运行时会抛 ArrayStoreException
如果允许:
List<String>[] arrays = new List<String>[10];
Object[] objs = arrays;
objs[0] = new ArrayList<Integer>(); // 危险!
由于运行时 List<String> 已变成 List,无法阻止错误元素进入数组,破坏了类型安全。
以下写法 编译错误:
T[] array = new T[10]; // ❌
List<String>[] listArray = new List<String>[10]; // ❌
因为:
T 的真实类型Object[] + 强制转换(不推荐但可用)T[] array = (T[]) new Object[size];
⚠️ 会有 unchecked warning
T[] array = (T[]) Array.newInstance(clazz, size);
List 代替数组(推荐)List<T> list = new ArrayList<>();
✅ 类型安全
✅ 无擦除问题
✅ 更灵活
List<?>[] lists = new List<?>[10]; // ✅
因为 ? 本身就不承诺具体类型
| 特性 | 泛型 | 数组 |
|---|---|---|
| 类型检查 | 编译期 | 运行期 |
| 类型信息 | 被擦除 | 保留 |
| 协变 | 不变 | 协变 |
➡ 两者本质冲突
➡ Java 选择 牺牲泛型数组的便利性,保住运行安全
Java 禁止泛型数组,是因为泛型在运行时被擦除,而数组需要在运行时保证类型安全,二者无法兼容。
如果你愿意,我也可以结合 源码示例 / JVM 层面 / 面试角度 再深入讲。
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。