参数化类型是不可变的。对两个不同类型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>。

第28条:利用有限制通配符来提升API的灵活性的更多相关文章

  1. Item 28 利用有限制通配符来提升API的灵活性

    <? extends E> 和<? super E>的使用   <? extends E>的使用 Item 26 这是堆栈的公有API: public class ...

  2. 第二十八条:利用有限制通配符来提升API的灵活性

    如第二十五条所述,参数化类型是不可变的.类型Type1和Type2而言,不管Type1与Type2的关系,List<Type1>既不是List<Type2>的子类型,也不是也不 ...

  3. Effective Java 第三版——31.使用限定通配符来增加API的灵活性

    Tips <Effective Java, Third Edition>一书英文版已经出版,这本书的第二版想必很多人都读过,号称Java四大名著之一,不过第二版2009年出版,到现在已经将 ...

  4. EffectiveJava(28)怎么利用有限制的通配符类型来提升API的灵活性

    有时候,我们需要的灵活性要比不可变类型所能提供的更多.所以针对一些通用性的方法,通常用泛型代替固定的数据类型,特别是当你要将某个方法打包成Jar的时候. 结合之前的例子,我们增加尝试用有限制的通配符类 ...

  5. effective-java学习笔记---使用限定通配符来增加 API 的灵活性31

    在你的 API 中使用通配符类型,虽然棘手,但使得 API 更加灵活. 如果编写一个将被广泛使用的类库,正确使用通配符类型应该被认为是强制性的. 记住基本规则: producer-extends, c ...

  6. MySQL必会的28条经典查询

    MySQL必会的28条经典查询   原创作品.转载请注明出处https://blog.csdn.net/kk123k 表结构及测试数据请看我上一篇文章:学生选修成绩表测试数据 Student(Sno, ...

  7. 利用 Django REST framework 编写 RESTful API

    利用 Django REST framework 编写 RESTful API Updateat 2015/12/3: 增加 filter 最近在玩 Django,不得不说 rest_framewor ...

  8. 利用Vert.x构建简单的API 服务、分布式服务

    目前已经使用Vertx已经一年多了,虽然没有太多的造诣,但也已在项目中推广了下:从最初的vertx搭建web服务,到项目上线运营,还算比较稳定.再到后来尝试搭建基于vertx的分布式服务,一路下来也积 ...

  9. jQuery:jQuery性能优化28条建议

    http://www.xue5.com/WebDev/jQuery/671700.html 直在寻找有关jQuery性能优化方面的小窍门,能让我那臃肿的动态网页应用变得轻便些.找了很多文章后,我决定将 ...

随机推荐

  1. 正确导入svn拉取的工程

    为什么要写这篇博文?主要是记录摸着石头过黄河的过程.之前在eclipse装了svn插件,拉取远程工程,在eclipse显示的工程,并不会分开显示模块工程,反而 是以总工程的姿态呈现.或许你觉得不管分模 ...

  2. 【25】考虑写出一个不抛异常的swap函数

    1.swap交换对象值,std提供了实现方法模版的实现,它的实现是交换对象值. namespace std { template<typename T> void swap(T& ...

  3. Struts2 Action的访问路径

    1.     Action的访问路径 扩展名 缺省以.action结尾,请参考:default.properties文件,可以通过配置改变这一点: <constant name="st ...

  4. wcf自身作为宿主的一个小案例

    第一步:创建整个解决方案 service.interface:用于定义服务的契约(所有的类的接口)引用了wcf的核心程序集system.ServiceModel.dll service:用于定义服务类 ...

  5. jquery实现无缝滚动

    //点击上一页 $('.pointLeft').click(function() { if (prevAllow) { prevAllow = false; scrollUlLeft = scroll ...

  6. Languages

    Languages A language class exists inside the system/Core folder, this class have 2 methods: load - L ...

  7. 聊聊 iOS 开发中的协议

    前言 何为协议,简单来说在OC中我们使用关键字@protocol可以声明一个协议,并在协议中添加多个属性.方法供于遵循者实现,从某个角度上来说,这是一种不同于category机制的category.在 ...

  8. centos6.5 安装jdk7和tomcat7

    JDK安装: 安装说明 系统环境:centos-6.5安装方式:rpm安装软件:jdk-7-linux-x64.rpm下载地址:http://www.oracle.com/technetwork/ja ...

  9. ORM之PetaPoco入门(一)--Petapoco简介

    1. ORM概括 1.1. ORM简介 ORM 对象-关系映射(Object/Relation Mapping,简称ORM),是随着面向对象的软件开发方法发展而产生的.面向对象的开发方法是当今企业级应 ...

  10. Android开发学习

    Android Studio中文社区:http://www.android-studio.org/ Android Studio官方网站地址:http://developer.android.com/ ...