泛型是 JDK 1.5 中引入的新特性, 首先我们来思考下 java 为什么要引入泛型, 我们看如下代码:
List list = new ArrayList();
list.add(55);
list.add("dd");
System.out.println(((Integer) list.get(1)) - 5);
这段代码在编译器是没有任何问题的, 可以通过编译, 但是运行时会得到 java.lang.ClassCastException 异常, 如果使用泛型的话,
List<Integer> list = new ArrayList<>();
list.add(55);
list.add("dd"); // 编译错误
System.out.println(((Integer) list.get(1)) - 5);
到这里我们明白了:
java 之所以引入泛型是为了增强程序的安全性和正确性, 以便在编译期就能检查出类型相关的错误.
那么既然这样, 为什么不能使用泛型数组呢? 首先假设如果可以使用泛型数组, 我们看下面一段代码:
List<Integer>[] list = new ArrayList<Integer>[10]; // 泛型数组
Object[] objects = list;
List<String> stringList = new ArrayList<>();
stringList.add("dd");
objects[0] = stringList;
Integer s = ((List<Integer>) objects[0]).get(0);
System.out.println(s);
如果可以使用泛型数组, 这段代码在编译期间没有任何问题, 但是在运行期又会出现烦人的 java.lang.ClassCastException , 我们来分析下为什么:
- 首先我们知道, java中的数组是可以向上转型成基类的数组的, 这个不用多说, java中的引用多态的机制.
- 然后我们知道 java 中的泛型实现的原理是类型擦除, 因此我们上面定义的 list<Integer> 和 list<String> 都会被擦除成 list<Object>, 所以我们可以在 objects 中加入 list<string> 这种类型的引用.
- 当我们加入 list<string> 这种类型的引用后, 如果我们按照原来定义泛型数组时使用的 list<integet> 类型来访问数组中的元素的话固然又会引入 java.lang.ClassCastException.
综上所述, 可以用一句话来描述 java 为什么不能创建泛型数组:
使用泛型的作用是使得程序在编译期可以检查出与类型相关的错误,但是如果使用了泛型数组,这种能力就会受到破坏.
参考博文:
https://blog.csdn.net/x_iya/article/details/79550667