9.6 泛型与数组
9.6 泛型与数组
Java
泛型有一个很重要的设计原则—如果——段代码在编译时没有提出“unchecked
未经检查的转换”警告,则程序在运行时不会引发ClassCastException
异常。
正是基于这个原因,所以数组元素的类型不能包含泛型变量或泛型形参,除非是无上限的类型通配符。但可以声明元素类型包含泛型变量或泛型形参的数组。也就是说,只能声明List<String>
形式的数组,但不能创建ArrayList<String>[10]
这样的数组对象。
不能创建ArrayList[10]这样的数组对象
反证法
假设Java
支持创建ArrayList<String>[10]
这样的数组对象,则有如下程序:
1 | // 下面代码实际上是不允许的 |
在上面代码中,如果1号代码是合法的,经过中间系列的程序运行,势必在2号代码处引发运行时异常,这就违背了Java
泛型的设计原则。
如果将程序中的1代码:
1 | List<String>[] lsa= new ArrayList<String>[10];// 1号代码 |
改为:
1 | List<String>[] lsa=new ArrayList[10]; |
其他不变:
1 | //下面代码编译时有“ [unchecked]未经检査的转换”警告 |
上面程序1号代码声明了List<String>
类型的数组变量,这是允许的;但不允许创建List<String>
囗类型的对象,所以创建了一个类型为ArrayList[10]
的数组对象,这也是允许的。
只是把ArrayList[10]
对象赋给List<String>
口变量时会有编译警告“unchecked]
未经检査的转换”’即编译器并不保证这段代码是类型安全的。
上面代码同样会在2号代码引发运行时异常,但因为编译器已经提出了警告,所以完全可能出现这种异常。
可以创建无上限的通配符泛型数组
Java
允许创建无上限的通配符泛型数组,例如new ArrayList<?>[10]
,因此也可以将第一段代码改为使用无上限的通配符泛型数组,在这种情况下,程序不得不进行强制类型转换。正如前面所介绍的,在进行强制类型转换之前应通过instanceof
运算符来保证它的数据类型。将上面代码改为如下形式:
1 | List<?>[] lsa = new ArrayList<?>[10]; |
不能创建元素类型是泛型的数组
与此类似的是,创建元素类型是泛型类型的数组对象也将导致编译错误。如下代码所示:
1 | <T> T[] makeArray (Collection<T> coll){ |