栏目分类:
子分类:
返回
终身学习网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
终身学习网 > IT > 软件开发 > 后端开发 > Java

java中泛型的不可协变性

Java 更新时间:发布时间: 百科书网 趣学号
泛型的不可协变性 原因

泛型是实现参数化多态的一种形式,泛型通过使用通配符来实现基于某个特定类型的类,这个特定的类型会在编译时被填充,会通过“类型擦除”来实现,例如:

定义了Set的泛型类,我们声明了 Set s1 = new Set(); 在编译阶段,编译器将其转化成为了真正的类Set_Integer,类中的T类型均会被替换为Integer,这也就是类型擦除的含义。

我们在使用泛型时,总会联想到有关继承的协变性或者逆变性,然而泛型实际上是不可协变的,也就是说不存在所谓的继承关系,这其中就和类型擦除的概念相关。

不妨以数组的协变性来举例:我们知道,如果类A是类B的子类,那么A[]是B[]的子类。我们可以写 Object[] obj = new String[]{};

这样的用法会成功通过编译器的检查。而且即便在obj中存放了非string对象,也会在运行时才报异常,静态检查阶段不会抛出异常,Object是String的父类,所以这是合法的。

然而当我们写 ArrayList obj = new ArrayList(); 编译却无法通过,这就是由于泛型的不可协变性的影响:编译器会对泛型进行类型擦除,从而生成新的类 ArrayList_Object 和 ArrayList_Integer,这样的两个类,不存在继承关系,不在继承树上有确切的父子关系,编译器无法new一个obj对象,自然也就出现了异常。

解决办法

那么怎样解决这个问题?我们可以利用通配符中的关键字extends和super,例如 ArrayList list = new ArrayList; 这样的语句是合法的,Java提供的通配符,一定程度上突破了泛型不可协变性的限制,例如:

// collection1可以存放任何类型  
Collection collection1 = new ArrayList();  
collection1 = newArrayList();  
collection1 = newArrayList();  
   
//collection3表示它可以存放Number或Number的子类    
Collection collection3 = null;  
collection3 = newArrayList();  
collection3 = newArrayList();  
collection3 = newArrayList();  
   
//collection4表示它可以存放Integer或Integer的父类    
Collection collection4 = null;  
collection4 = newArrayList();  

转载请注明:文章转载自 www.051e.com
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 ©2023-2025 051e.com

ICP备案号:京ICP备12030808号