参数化类型是不可变的。对两个不同类型T1和T2而言,List<T1>与List<T2>没有父子类型关系。

考虑:

public class Stack<E> {
public Stack();
public void push(E e);
public E pop();
public boolean isEmpty();
}

假设增加一个方法,按顺序将一系列的元素放到堆栈中:

public void pushAll(Iterable<E> src) {
for(E e : src)
push(e);
}

如果尝试这样做:

Stack<Number> s = new Stack<Number>();
Iterable<Integer> i = ...;
s.pushAll(integers);

从逻辑上讲,这样应该是允许的,因为Integer是Number的子类,应当允许将Integer放到类型为Number的堆栈中。

但实际运行的时候会提示Iterable<Number>与Iterable<Integer>不兼容。

有限制的通配符类型可以处理这种情况:

pushAll的输入参数不应该是“E的Iterable接口”,而应该为“E的某个子类型的Iterable接口”,修改为Iterable<? extends E>

假设添加一个popAll方法,从堆栈中弹出每个元素,添加到指定集合中:

public void popAll(Collection<E> dst) {
while(!isEmpty) {
dst.add(pop());
}
}

与未修改的putAll一样,应当允许类型为Number的栈帧放在包括Number在内的父类型中。

所以,修改为:

public void popAll(Collection<? super E> dst) {
while(!isEmpty) {
dst.add(pop());
}
}

在putAll方法中,输入参数的角色是生产者,因为参数提供数据给堆栈使用,在popAll方法中,输入参数的角色是消费者,因为堆栈提供数据给参数使用。总之,如果参数化类型表示一个T生产者,就使用<? extends T>,如果表示一个T的消费者,就使用<? super T>。

最新文章

  1. MYSQL 按照字母排序查询
  2. uva 11174 Stand in a Line
  3. Appium 点击Android屏幕
  4. 蓝桥杯之FBI树问题
  5. Uva 11889 Benefit (lcm与gcd)
  6. vue2.x利用脚手架快速构建项目并引入bootstrap、jquery
  7. zoj 3195 Design the city LCA Tarjan
  8. 四 : springMVC各种跳页面传值
  9. iOS-CYLTabBarController【好用的TabbarController】
  10. spring cloud + .net core实现微服务架构
  11. zabbix自定义监控项、添加图形、设置触发器、远程执行命令
  12. Recurrent Neural Network[Content]
  13. MySQL学习笔记Windows篇&lt;一&gt; Welcome to MySQL
  14. (Arrays.sort() 或 map) Ignatius and the Princess IV hdu1029
  15. 复选框批量删除操作-jquery方式
  16. python装饰器概念与应用
  17. 允许mysql远程用户连接。
  18. 在ASP.NET MVC中使用Knockout实践09,自定义绑定
  19. How to disable SSL certificate checking with Spring RestTemplate?(使用resttemplate访问https时禁用证书检查)
  20. 《Linux多线程服务端编程——使用muduo C++网络库》读书笔记

热门文章

  1. Xcode8 创建NSManageObject subclass方法
  2. 创建性能监视器(logman)
  3. 为什么for不能有序遍历数组的所有元素?(Array的设计原理)
  4. 学习笔记之JAVA多线程
  5. [000]socket通信--server和client实现的简单例子
  6. Ext.Net 问题收集
  7. 【转】cocos2d-x 2.0版本 自适应屏幕分辨率
  8. 数据库中的DDL和DML语言
  9. MySQL(2):SQL语言的分类
  10. 深入理解计算机系统第二版习题解答CSAPP 2.14