参数化类型是不可变的。对两个不同类型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. mybatis-generator-core自动生成do、mapping、dao 代码

    使用mybatis配置映射文件,有点麻烦,容易出错,可以使用jar工具自动生成代码,即高效又方便 一.下载两个jar,并放置在G:\tool\maven\generator目录下(自己定义) myba ...

  2. 教你50招提升ASP.NET性能(十):减少通过网络发送的数据

    (16)Reduce the data sent across the network 招数16: 减少通过网络发送的数据 Reducing the amount of data sent acros ...

  3. Lync安装随笔

    使用域管理员权限扩展架构 1.iis角色安装 2.net3.5,消息队列服务器.目录服务集成.桌面体验.AD DS和AD LDS工具(远程服务管理工具中),启用WindowsFirewall服务 3. ...

  4. C#-动态生成40个按钮,大小(20,20),要求每行6个放置

    应该为for (int i=0;i<基本数据DataSet3.Tables [0].Rows .Count ;i++)                 {                 int ...

  5. Android应用插件式开发解决方法[转]

    一.现实需求描述 一般的,一个Android应用在开发到了一定阶段以后,功能模块将会越来越多,APK安装包也越来越大,用户在使用过程中也没有办法选择性的加载自己需要的功能模块.此时可能就需要考虑如何分 ...

  6. pomelo 开发环境搭建

    开发前提条件:  Windows系统,请确保你的Windows系统包括源代码编译工具.Node.js的源代码主要由C++代码和JavaScript代码构成,可是却用gyp工具来做源代码的项目管理,该工 ...

  7. [node.js]RPC(远程过程调用)的实现原理

    刚接触到RPC(远程过程调用),就是可以在本地调用远程机子上的程序的方法,看到一个简单的nodejs实现,用来学习RPC的原理很不错:nodejs light_rpc   使用示例:   //服务端 ...

  8. 性能测试中用LambdaProbe监控Tomcat Tomcat和Probe的配置

    转载:http://bbs.51testing.com/thread-90047-1-1.html 性能测试中用LambdaProbe监控TomcatLambdaProbe 是一款强大的免费开源工具, ...

  9. C#基础篇--文件(流)

    1:Path类是专门用来操作文件路径的(Path类是静态类):当然用字符串的处理办法也能实现.  string str = @"C:\Users\成才\Desktop\Hashtable.t ...

  10. js原生bind()用法[注意不是jquery里面的bind()]

    <div id="a"> <div></div> <div></div> <div></div> ...