Java泛型与数组
1.* 泛型与数组
Java 5的泛型有一个很重要的设计原则,如果一段代码在编译时没有提出[unchecked]未经检查的转换警告,则程序在运行时不会引发ClassCastException异常。正是基于这个原因,所以数组元素的类型不能包含类型变量或类型形参,除非是无上限的类型通配符。但可以声明元素类型包含类型变量或类型形参的数组。也就是说,只能声明List<String>[]
形式的数组,但不能创建ArrayList<String>[10]
这样的数组对象。
假设Java支持创建ArrayList<String>[10]
这样的数组对象,则有如下程序:
点击查看代码
//下面代码实际上是不允许的
List<String>[] lsa = new List<String>[10];
//强制类型转换为一个Object数组
Object[] oa = (Object[])lsa;
List<Integer> li = new ArrayList<Integer>();
li.add(new Integer(3));
//将List<Integer>对象作为oa的第二个元素
//下面代码没有任何警告
oa[1] = li;
//下面代码也不会有任何警告,但将引发ClassCastException异常
String s = lsa[1].get(0);
在上面代码中,如果List<String>[] lsa = new List<String>[10]
代码是合法的,经过中间系列的程序运行,势必在String s = lsa[1].get(0)
处引发运行时异常,这就违背了Java泛型的设计原则。
如果将程序改为如下形式:
点击查看代码
//下面代码编译时有“[unchecked]未经检查的转换”警告
List<String>[] lsa = new ArrayList[10];
Object[] oa = (Object[]) lsa;
List<Integer> li = new ArrayList<Integer>();
li.add(new Integer(3));
oa[1] = li;
//下面代码引起ClassCastException异常
String s = lsa[1].get(0);
上面程序List<String>[] lsa = new ArrayList[10]
声明了List<String>[]
类型的数组变量,这是允许的;但不允许创建List<String>[]
类型的对象,所以创建了一个类型为ArrayList[10]的数组对象,这也是允许的。只是把ArrayList[10]对象赋给List<String>[]
变量时会有编译警告[unchecked]未经检查的转换,即编译器并不保证这段代码是类型安全的。上面代码同样会在String s = lsa[1].get(0)
处引发运行时异常,但因为编译器已经提出了警告,所以完全可能出现这种异常。
Java允许创建无上限的通配符泛型数组,例如new ArrayList<?>[10]
,因此也可以将第一段代码改为使用无上限的通配符泛型数组,在这种情况下,程序不得不进行强制类型转换。如下代码所示:
点击查看代码
List<?>[] lsa = new ArrayList<?>[10];
Object[] oa = (Object[]) lsa;
List<Integer> li = new ArrayList<Integer>();
li.add(new Integer(3));
oa[1] = li;
//下面代码引发ClassCastException异常
String s = (String)lsa[1].get(0);
编译上面代码不会发出任何警告,运行上面程序将在String s = (String)lsa[1].get(0)
引发ClassCastException异常。因为程序需要将lsa的第一个数组元素的第一个集合元素强制类型转换为String类型,所以程序应该自己通过instanceof运算符来保证它的数据类型。即改为如下形式:
点击查看代码
List<?>[] lsa = new ArrayList<?>[10];
Object[] oa = (Object[]) lsa;
List<Integer> li = new ArrayList<Integer>();
li.add(new Integer(3));
oa[1] = li;
Object target = lsa[1].get(0);
if (target instanceof String){
//下面代码安全了
String s = (String) target;
}
与此类似的是,创建元素类型是类型变量的数组对象也将导致编译错误。如下代码所示:
点击查看代码
<T> T[] makeArray(Collection<T> coll){
//下面代码导致编译错误
return new T[coll.size()];
}
因为类型变量在运行时并不存在,所以编译器无法确定实际类型是什么。
标签:Java,lsa,代码,List,li,数组,泛型,new,ArrayList From: https://www.cnblogs.com/hzhiping/p/16906448.html