JAVA泛型中的有界类型(extends super)(转)
JDK1.5中引入了泛型(Generic)机制。泛型的本质是参数化类型,也就是说所操作的数据类型被指定为一个参数。这种参数类型可以用在类、接口和方法的创建中,分别称为泛型类、泛型接口、泛型方法。
Java语言引入泛型的好处是安全简单,在编译的时候检查类型安全,并且所有的强制转换都是自动和隐式的,提高代码的重用率。
JAVA泛型的规则和限制
- 泛型的类型参数只能是类类型(包括自定义类),不能是简单类型。
- 同一种泛型可以对应多个版本(因为参数类型是不确定的),不同版本的泛型类实例是不兼容的。
- 泛型的类型参数可以有多个。
- 泛型的参数类型可以使用extends语句,例如<T extends superclass>。习惯上称为“有界类型”。
- 泛型的参数类型还可以是通配符类型。例如Class<?> classType = Class.forName(java.lang.String);
限制泛型的可用类型
如果我们要限制class GenericsFoo<T>类型持有者T的范围为集合接口类型,只需使用class GenericsFoo<T extends Collection>,这样类中的泛型T只能是Collection接口的实现类,传入非Collection接口编译会出错。
通配符泛型
为了解决类型不能动态根据实例来确定的缺点,引入了“通配符泛型”,使得一个参数可以用来表示一组实例化后的模板。
其中,
“?”代表未知类型
extends关键字声明了类型的上界,表示参数化的类型可能是所指定的类型,或者是此类型的子类
super关键字声明了类型的下界,表示参数化的类型可能是所指定的类型,或者是此类型的父类型,直至Object
上界
- public void upperBound(List<? extends Date> list, Date date)
- {
- Date now = list.get(0);
- System.out.println("now==>" + now);
- //list.add(date); //这句话无法编译
- list.add(null);//这句可以编译,因为null没有类型信息
- }
无法编译的原因就在于,实际调用时传入的list可能是java.util.Date的某个子类的参数化类型,如:
- public void testUpperBound()
- {
- List<Timestamp> list = new ArrayList<Timestamp>();
- Date date = new Date();
- upperBound(list,date);
- }
也就是说,upperBound方法中实际的list是List<Timestamp>,向它添加一个基类Date类型,由于基类无法转换为子类,所以无法添加。相反,读取数据时,不管实际的list是什么类型,但可以知道它至少会返回一个Date类型,所以用foreach,get等没有问题。
下界
先看示例代码:
- public void lowerBound(List<? super Timestamp> list)
- {
- Timestamp now = new Timestamp(System.currentTimeMillis());
- list.add(now);
- //Timestamp time = list.get(0); //不能编译
- }
不能编译的原因是调用代码可能是这样的:
- public void testLowerBound()
- {
- List<Date> list = new ArrayList<Date>();
- list.add(new Date());
- lowerBound(list);
- }
在lowerBound方法中的List<? super Timestamp>表示这个list的参数类型可能是Timestamp或Timestamp的父类,如后面的代码里,实际传入的是一个List<Date>类型。List<Date>中可以添加一个Timestamp对象,但list.get()方法返回的对象类型可能是Date甚至是Object,不能安全的向下转换到Timestamp,也就因此无法编译了。
小结一下就是:上界add方法受限,下界get方法受限。
泛型方法
是否拥有泛型方法,与其所在的类是否泛型没有关系。要定义泛型方法,只需将泛型参数列表置于返回值前。如:
public <T> void f(T x) {}
使用泛型方法时,不必指明参数类型,编译器会自己找出具体的类型。泛型方法除了定义不同,调用就像普通方法一样。
最后,需要注意的是,一个static方法,无法访问泛型类的类型参数,因为类还没有实例化,所以,若static方法需要使用泛型能力,必须使其成为泛型方法。
参考文献:
1. 百度百科: http://baike.baidu.com/view/1436058.htm
2. http://fyting.javaeye.com/blog/122732
JAVA泛型中的有界类型(extends super)(转)的更多相关文章
- 关于JAVA泛型中的通配符类型
之前对JAVA一知半解时就拿起weiss的数据结构开始看,大部分数据结构实现都是采取通配符的思想,好处不言而喻. 首先建立两个类employee和manager,继承关系如下.其次Pair类是一个简单 ...
- Java泛型中extends和super的理解(转)
E – Element (在集合中使用,因为集合中存放的是元素) T – Type(Java 类) K – Key(键) V – Value(值) N – Number(数值类型) ? – 表示不确定 ...
- java泛型中extends 和 super的区别
一般对泛型中extends 和 super 的区别是这样介绍的: 关键字说明 ? 通配符类型 <? extends T> 表示类型的上界,表示参数化类型的可能是T 或是 T的子类 < ...
- Java泛型中extends和super的理解
作者:zhang siege链接:https://www.zhihu.com/question/20400700/answer/91106397来源:知乎著作权归作者所有.商业转载请联系作者获得授权, ...
- Java泛型中extends和super的区别?
<? extends T>和<? super T>是Java泛型中的"通配符(Wildcards)"和"边界(Bounds)"的概念. ...
- JAVA泛型知识(二)--> <? extends T>和<? super T>
<? extends T> 和 <? super T> 是Java泛型中的“通配符(Wildcards)” 和 “边界(Bounds)”的概念 <? extends T& ...
- Java泛型中<?> 和 <? extends Object>的异同分析
相信很多人和我一样,接触Java多年,却仍旧搞不清楚 Java 泛型中 <?>和 <? extends Object>的相似和不同.但是,这应该是一个比较高端大气上档次的Que ...
- Java泛型中的细节
Java泛型中的细节 如果没有泛型 学习Java,必不可少的一个过程就是需要掌握泛型.泛型起源于JDK1.5,为什么我们要使用泛型呢?泛型可以使编译器知道一个对象的限定类型是什么,这样编译器就可以在一 ...
- 【转】聊一聊-JAVA 泛型中的通配符 T,E,K,V,?
原文:https://juejin.im/post/5d5789d26fb9a06ad0056bd9 前言 Java 泛型(generics)是 JDK 5 中引入的一个新特性, 泛型提供了编译时类型 ...
随机推荐
- 20155203 2016-2017-3 《Java程序设计》第5周学习总结
20155203 2016-2017-3 <Java程序设计>第5周学习总结 教材学习内容总结 课堂知识总结 封装是继承的基础,继承是多态的基础.多态是用父类声明对象的引用,用子类生成对象 ...
- Linux 并发链接数
并发数查看 查看 TCP 协议连接数 netstat -n | awk '/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}' SYN_RECV # ...
- 编写安全的API接口
HTTPS接口参数加密签名设计思路 数名 类型 必选 描述 _appid string 是 调用方身份ID,接口提供方用此来识别调不同的调用者,该参数是API基本规范的一部分,请详见API公共规范. ...
- centos7系统下安装配置jdk、tomcat教程
JDK安装与配置 1.下载linux版本的jdk,我下的版本是jdk6.0,下载rpm版本的. 可通过百度搜索文件名:jdk-6u45-linux-x64-rpm.bin下载 也可通过oracle官网 ...
- poj2679
题意:给出一个有向图,每条边有两个属性:一个长度一个费用.费用可能是负数.长度一定是非负的.给出一个起点和一个终点,现要求,从起点走到终点,且从每个点走出时选择的那条边必须是以该点作为起点的边中费用最 ...
- tensorflow中的kernel/Adam 变量的来源
原因是使用Adam优化函数时,Adam函数会创建一个Adam变量,目的是保存你使用tensorflow创建的graph中的每个可训练参数的动量, words/_word_embeddings:0 bi ...
- LeetCode(15):三数之和
Medium! 题目描述: 给定一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?找出所有满足条件且不重复的三元组. 注意:答 ...
- Oracle学习笔记:a inner join b与from a,b where a.x=b.x的差异
近期,在使用Oracle的过程中,由以下两段代码的执行引发的思考,到底 select * from a,b where a.id = b.id 和 select * from a inner join ...
- docker:定制node.js的版本
本想用alpine,但如果想使用node.js 6.3.1版本的软件, 总会搞不定glibc和libstdc++报一个无法识别版本信息的错误. 搞了一天,算了.使用debian:stretch-sli ...
- hibernate Validator 6.X 的学习,bean的约束(主要包括的是容器元素的验证)
1. 四:案例二(property的验证) 1.