JAVA泛型通配符 extends 和 super
来源:互联网 发布:淘宝淘金币在哪看 编辑:程序博客网 时间:2024/05/17 02:01
在Java泛型使用中使用“?”作为类型的通配符。《Effective
Java》第28条,使用通配符可以提高API的灵活性。
但是通配符也使得泛型的使用变得更加复杂。
泛型类型是不可变
首先泛型类型是不可变的,比如List< String >就不是List< Object >的子类型,而是两个独立的类型。如下
List<String> strs = new ArrayList<String>();List<Object> objs = strs; //编译错误,类型不匹配(imcompatible type)
假如可编译通过的话,会带来新的问题,导致运行时错误
objs.add(1); // Here we put an Integer into a list of StringsString s = strs.get(0); // !!! ClassCastException: Cannot cast Integer to String
所以为了确保运行时类型安全,Java泛型设计成不可变的。
但是这种不可变的泛型类型,又会带来下面问题:定义一个泛型,为“Collection”增加一个addAll方法,如下实现:
interface Collection<E> ... { void addAll(Collection<E> items);}
那么在将“Collection< Object >”中添加“Collection< String >”,该方法就没法使用了,而理论上应该是合法的,因为String是Object的子类,是可以添加到父类的集合中
void copyAll(Collection<Object> to, Collection<String> from) { to.addAll(from); // 编译不通过: //Collection<String> 不是 Collection<Object>的子类型}
为了解决该问题,Java中使用了类型通配符方式来解决,如下
interface Collection<E> ... { void addAll(Collection<? extends E> items);}
通配符的上界
? extends T 其中T表示通配符的上界,表示该方法可以接收T以及T的子类。意味着可以安全的读T(所有实例都是T的子类)的实例,但是不能向其添加元素,因为没法确定添加的实例类型跟定义的类型是否匹配。
//Bird Cat都是Animal的子类public void testAdd(List<? extends Animal> list) { //下面都会报编译错误的 //因为testAdd方法传入的list的类型不确定的,(有可能是List<Cat>,List<Dog>)就没法确保它可以添加下面的全部类型 //若传入“List<Bird>”,只能add(bird),只有②可以添加 //若传入“List<Dog>”,都不能添加 list.add(new Animal("animal")); //① list.add(new Bird("bird")); //② list.add(new Cat("cat")); //③ for(Animal a:list){ //但是可以读取里面的元素,因为他们都是Animal的子类型 }}
可以理解成:“Collection< String> ”是“Collection< ? extends Object >”的子类型。
这种通配符(wildcard )是通过继承一个范围类(通配符上界,upper bound)来实现类型协变。
通配符的下界
? super T(T表示通配符的下界),表示该方法可以接收T及T的父类参数。意味着可以安全的添加元素,但是不能读取。
public void testAdd2(List<? super Animal> list){ //可以编译通过,因为传入的T类型肯定是Animal的父类,也是Bird,Cat的父类 list.add(new Animal("animal")); list.add(new Bird("bird")); list.add(new Cat("cat")); for(Animal a:list){ //但是不能读取,因为父类不能转换成子类 } }
可以理解成:“Collection< ? super String > ”是“Collection< String >”的父类型;可以调用集合将String作为参数的方法(如:add(String) or set(int, String));但当从集合中获取元素时,得到是Objec对象而不是String对象。
PECS
PECS stands for Producer-Extends,Consumer-Super
- extends
通配符的上界方式,只能从中读取元素,不能添加元素,形象的称为生产者(Producers)
- super
通配符的下界方式,只能添加元素,没法直接读取下界类型的元素,形象的称为消费者(Consumers)
- JAVA泛型通配符 extends 和 super
- Java-泛型编程-使用通配符? extends 和 ? super
- Java-泛型编程-使用通配符? extends 和 ? super
- Java-泛型编程-使用通配符? extends 和 ? super
- Java 泛型通配符extends 与 super
- Java泛型通配符extends与super
- Java泛型通配符extends与super
- Java泛型通配符extends与super
- Java泛型通配符extends与super
- Java泛型通配符extends与super
- Java泛型通配符extends与super
- Java泛型通配符extends与super
- Java泛型通配符<? extends T>与<? super T>
- Java泛型通配符<? extends T>与<? super T>
- Java泛型通配符<? extends T>与<? super T>
- Java泛型通配符<? extends T>与<? super T>
- java泛型中的通配符 extends与super
- 简述泛型通配符<? extends T>和<? super T>
- Unity3D 获取与设置对象Transform组件下的position,rotation
- hello 大家好
- 工厂模式
- PHP中级程序员常见面试题
- Linux部署maven项目
- JAVA泛型通配符 extends 和 super
- Android常用控件(按钮、选择框、日期时间控件)
- ubuntu配置tomcat7(已测有效)
- 程序学3DMax之自动展UV
- 16年程序员平均工资122478元_你拖后腿了没?
- datatable对某一列的值进行模糊或非模糊搜索
- 习题27
- 哈夫曼压缩算法C语言实现——步骤,详细注释源码
- 统计学习方法