首先要注意,泛型在引入的初衷之一就是为了安全,可以在编译时期检查出问题,而且运行时期泛型会被擦除掉也检查不出问题(为什么运行时期会擦除?因为这样做不必修改 JVM
(运行时期),减少了潜在的大幅改动和随之而来的风险,也许同时也反映出 Java Bytecode
规范在设计之初的先天不足;同时不管是 List<String>
还是 List<Integer>
还是原生 List
在运行时期实际类型都是 List<Object>
也是为了兼容低版本没有泛型的代码,将 List<>
与 List
一视同仁)。
那为什么泛型不能定义数组呢,先看看 Java
中数组有什么问题
Java 数组是具有协变性的,例如:
Integer[] is = new Integer[1]; Object[] os = is; os[0] = "hhh";
这三行代码在编译期不会报错,但是会在运行期报错。
而泛型只能在编译期检查问题,因为在运行期泛型会被擦除。
如果泛型可以定义数组的话会怎么样,看个例子:
List<Integer>[] is = new ArrayList<>[1]; Object[] os = is; os[0] = new ArrayList<String>();
跟上面的同理,编译器不会查出错误,而运行期泛型会被擦除变成:
List<Object>[] is = new ArrayList<>[1]; Object[] os = is; os[0] = new ArrayList<Object>();
就更不能检查出问题了,安全问题会一直存在,而 Java
号称自己是"类型安全"语言,不会意外怀孕,肯定不会允许这种情况出现
总结一下:
第一,添加泛型的时候 Java
选择的是减少修改 JVM
而带来不必要的风险选择了泛型擦除这种手段,所以在运行时期检查不出泛型的错误。
第二,Java
数组是具有协变性的,有继承关系的可以随便乱放,编译时期不会报错,但是就算这样运行时期也会报错,但是泛型数组要是逃过了编译时期的检查,运行时期泛型就会被擦除掉,检查不会错误。
综上所述, Java
强制不允许泛型定义数组。