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()];
}

因为类型变量在运行时并不存在,所以编译器无法确定实际类型是什么。

原文地址:http://www.cnblogs.com/hzhiping/p/16906448.html

1. 本站所有资源来源于用户上传和网络,如有侵权请邮件联系站长! 2. 分享目的仅供大家学习和交流,请务用于商业用途! 3. 如果你也有好源码或者教程,可以到用户中心发布,分享有积分奖励和额外收入! 4. 本站提供的源码、模板、插件等等其他资源,都不包含技术服务请大家谅解! 5. 如有链接无法下载、失效或广告,请联系管理员处理! 6. 本站资源售价只是赞助,收取费用仅维持本站的日常运营所需! 7. 如遇到加密压缩包,默认解压密码为"gltf",如遇到无法解压的请联系管理员! 8. 因为资源和程序源码均为可复制品,所以不支持任何理由的退款兑现,请斟酌后支付下载 声明:如果标题没有注明"已测试"或者"测试可用"等字样的资源源码均未经过站长测试.特别注意没有标注的源码不保证任何可用性