JDK1.5中引入了泛型(Generic)机制。泛型的本质是参数化类型,也就是说所操作的数据类型被指定为一个参数。这种参数类型可以用在类、接口和方法的创建中,分别称为泛型类、泛型接口、泛型方法。

Java语言引入泛型的好处是安全简单,在编译的时候检查类型安全,并且所有的强制转换都是自动和隐式的,提高代码的重用率。

JAVA泛型的规则和限制

  1. 泛型的类型参数只能是类类型(包括自定义类),不能是简单类型。
  2. 同一种泛型可以对应多个版本(因为参数类型是不确定的),不同版本的泛型类实例是不兼容的。
  3. 泛型的类型参数可以有多个。
  4. 泛型的参数类型可以使用extends语句,例如<T extends superclass>。习惯上称为“有界类型”。
  5. 泛型的参数类型还可以是通配符类型。例如Class<?> classType = Class.forName(java.lang.String);

限制泛型的可用类型

如果我们要限制class GenericsFoo<T>类型持有者T的范围为集合接口类型,只需使用class GenericsFoo<T extends Collection>,这样类中的泛型T只能是Collection接口的实现类,传入非Collection接口编译会出错。

通配符泛型

为了解决类型不能动态根据实例来确定的缺点,引入了“通配符泛型”,使得一个参数可以用来表示一组实例化后的模板。

其中,

“?”代表未知类型

extends关键字声明了类型的上界,表示参数化的类型可能是所指定的类型,或者是此类型的子类

super关键字声明了类型的下界,表示参数化的类型可能是所指定的类型,或者是此类型的父类型,直至Object

上界

  1. public void upperBound(List<? extends Date> list, Date date)
  2. {
  3. Date now = list.get(0);
  4. System.out.println("now==>" + now);
  5. //list.add(date); //这句话无法编译
  6. list.add(null);//这句可以编译,因为null没有类型信息
  7. }

无法编译的原因就在于,实际调用时传入的list可能是java.util.Date的某个子类的参数化类型,如:

  1. public void testUpperBound()
  2. {
  3. List<Timestamp> list = new ArrayList<Timestamp>();
  4. Date date = new Date();
  5. upperBound(list,date);
  6. }

也就是说,upperBound方法中实际的list是List<Timestamp>,向它添加一个基类Date类型,由于基类无法转换为子类,所以无法添加。相反,读取数据时,不管实际的list是什么类型,但可以知道它至少会返回一个Date类型,所以用foreach,get等没有问题。

下界

先看示例代码:

  1. public void lowerBound(List<? super Timestamp> list)
  2. {
  3. Timestamp now = new Timestamp(System.currentTimeMillis());
  4. list.add(now);
  5. //Timestamp time = list.get(0); //不能编译
  6. }

不能编译的原因是调用代码可能是这样的:

  1. public void testLowerBound()
  2. {
  3. List<Date> list = new ArrayList<Date>();
  4. list.add(new Date());
  5. lowerBound(list);
  6. }

在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)(转)的更多相关文章

  1. 关于JAVA泛型中的通配符类型

    之前对JAVA一知半解时就拿起weiss的数据结构开始看,大部分数据结构实现都是采取通配符的思想,好处不言而喻. 首先建立两个类employee和manager,继承关系如下.其次Pair类是一个简单 ...

  2. Java泛型中extends和super的理解(转)

    E – Element (在集合中使用,因为集合中存放的是元素) T – Type(Java 类) K – Key(键) V – Value(值) N – Number(数值类型) ? – 表示不确定 ...

  3. java泛型中extends 和 super的区别

    一般对泛型中extends 和 super 的区别是这样介绍的: 关键字说明 ? 通配符类型 <? extends T> 表示类型的上界,表示参数化类型的可能是T 或是 T的子类 < ...

  4. Java泛型中extends和super的理解

    作者:zhang siege链接:https://www.zhihu.com/question/20400700/answer/91106397来源:知乎著作权归作者所有.商业转载请联系作者获得授权, ...

  5. Java泛型中extends和super的区别?

    <? extends T>和<? super T>是Java泛型中的"通配符(Wildcards)"和"边界(Bounds)"的概念. ...

  6. JAVA泛型知识(二)--> <? extends T>和<? super T>

    <? extends T> 和 <? super T> 是Java泛型中的“通配符(Wildcards)” 和 “边界(Bounds)”的概念 <? extends T& ...

  7. Java泛型中<?> 和 <? extends Object>的异同分析

    相信很多人和我一样,接触Java多年,却仍旧搞不清楚 Java 泛型中 <?>和 <? extends Object>的相似和不同.但是,这应该是一个比较高端大气上档次的Que ...

  8. Java泛型中的细节

    Java泛型中的细节 如果没有泛型 学习Java,必不可少的一个过程就是需要掌握泛型.泛型起源于JDK1.5,为什么我们要使用泛型呢?泛型可以使编译器知道一个对象的限定类型是什么,这样编译器就可以在一 ...

  9. 【转】聊一聊-JAVA 泛型中的通配符 T,E,K,V,?

    原文:https://juejin.im/post/5d5789d26fb9a06ad0056bd9 前言 Java 泛型(generics)是 JDK 5 中引入的一个新特性, 泛型提供了编译时类型 ...

随机推荐

  1. [转载]Juicer – 一个Javascript模板引擎的实现和优化

    http://ued.taobao.org/blog/2012/04/juicer-%E4%B8%80%E4%B8%AAjavascript%E6%A8%A1%E6%9D%BF%E5%BC%95%E6 ...

  2. MFS - MooseFS 文件系统

    MFSMooseFS 文件系统 可以实现RAID 功能:节约成本 实现在线扩展:是一种半分布式文件系统. 一.MFS文件系统的组成 1.mfsmaster 元数据服务器. 在整个体系中负责管理管理文件 ...

  3. Eric6启动时“无法定位序数4540于动态链接库LIBEAY32.dll”的错误

    参考自:https://blog.csdn.net/HongAndYi/article/details/80721478 在安装PyQt5的编程环境时,安装Eric6-17.12后运行eric6,却出 ...

  4. Python内置模块与标准库

    Python内置模块就是标准库(模块)吗?或者说Python的自带string模块是内置模块吗? 答案是:string不是内置模块,它是标准库.也就是说Python内置模块和标准库并不是同一种东西. ...

  5. Python 入门基础2 --基本数据类型、运算符

    本节目录 一.IDE(集成环境的安装) 二.基本数据类型 三.输入输出 四.运算符 五.后期补充内容 一.IDE(集成环境的安装) 安装pycharm 注:快捷键: 1.ctrl + ? :注释此行, ...

  6. .NET 的 WCF 和 WebService 有什么区别?(转载)

    [0]问题: WCF与 Web Service的区别是什么? 和ASP.NET Web Service有什么关系? WCF与ASP.NET Web Service的区别是什么? 这是很多.NET开发人 ...

  7. 在SharePoint 2013里配置Excel Services

    配置步骤,请参看下面两篇文章 http://www.cnblogs.com/jianyus/p/3326304.html https://technet.microsoft.com/zh-cn/lib ...

  8. 转:vue-router 2.0 常用基础知识点之router.push()

    转载地址:http://www.jianshu.com/p/ee7ff3d1d93d router.push(location) 除了使用 <router-link> 创建 a 标签来定义 ...

  9. hdu 6118度度熊的交易计划(费用流)

    度度熊的交易计划 Time Limit: 12000/6000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total S ...

  10. .NetCore WebApi利用Swagger文档实现选择文件上传

    介绍 实现这个功能主要还是依赖过滤器 在Swagger中利用 IOperationFilter 操作来实现文件上传 与之前处理结合Idr4授权一样的处理方式,不同的是授权处理的是Security,而文 ...