Java 泛型之 Type 体系

本贴最后更新于 2592 天前,其中的信息可能已经水流花落

Type 是 java 类型信息体系中的顶级接口,其中 Class 就是 Type 的一个直接实现类。此外,Type 还有有四个直接子接口:ParameterizedType,TypeVariable,WildcardType,GenericArrayType。

这几个接口的介绍如下:

  • Type

它是所有类型的公共接口。包括原始类型、参数化类型、数组类型、类型变量和基本类型。ParameterizedType, TypeVariable, WildcardType,GenericArrayType 这四个接口都是它的子接口。

  • GenericDeclaration

这个接口 Class、Method、Constructor 都有实现,我们就是要用这个接口的 getTypeParameters 方法,它返回一个 TypeVariable[]数组,这个数组里面就是我们定义的类型变量 T 和 K,顺序与我们声明时一样。如果用循环语句将数组打印出来,你会发现只会输出 T 和 K,这可不是我们想要的结果,那么想要获得预期的结果怎么办呢?请继续往下看。

  • TypeVariable

它表示类型变量。比如 T,比如 K extends Comparable<? super T> & Serializable,这个接口里面有个 getBounds()方法,它用来获得类型变量上限的 Type 数组,如果没有定义上限,则默认设定上限为 Object,请注意 TypeVariable 是接口,实际得到的是 TypeVariableImpl 实现类,下面几个接口都一样。

拿 T 和 K 来说明,T 没有定义任何上限,所以它就有一个默认上限 java.lang.Object,实际跟踪代码的时候你会发现 T 的 bounds 属性为空,只有在调用了 getBounds()方法后,才会有一个 Type[1]数组[class java.lang.Object]。而对于 K 来说,调用了 getBounds 方法后,得到的数组是[java.lang.Comparable<? super T>, interface java.io.Serializable],它们的类型却是不一样的,第 1 个是 ParameterizedType,而第二个是 Class.

  • ParameterizedType

ParameterizedType 表示参数化类型,就是上面说的 java.lang.Comparable<? super T>,再比如 List,List,这些都叫参数化类型。得到 Comparable<? super T> 之后,再调用 getRawType()与 getActualTypeArguments()两个方法,就可以得到声明此参数化类型的类(java.lang.Comparable)和实际的类型参数数组([? super T]),而这个? super T 又是一个 WildcardType 类型。

  • WildcardType

它用来描述通配符表达式,上面返回的? super T 正好是这个类型。然后调用 getUpperBounds()上限和 getLowerBounds()下限这两个方法,获得类型变量?的限定类型(上下限),对于本例的通配符(?),它的上限为 java.lang.Object,下限为 T

通过上面几个接口的分析,可以将 Person 类的泛型参数都解析出来,那么 Person 的超类以及实现的接口该怎么处理呢?Class 类里面同样在 1.5 版本加入了 getGenericSuperclass()与 getGenericInterfaces()两个方法,用于返回带参数化类型的超类与接口。

GenericArrayType 其实就是泛型数组类型。

我们说 Class 在一定程度上挽救了擦除的类型信息,我们就可以通过这几个接口来获取被擦除的类型参数信息,这几个接口无非就是对类型参数的一个分类,通过它们提供的一些方法,我们可以逐步的获取到最原始的类型参数的 Class 对象。

具体的说明和 API 大家可以去看文档,我这里记录一个实际的应用,当然在各种框架中的应用比比皆是。

在 JavaEE 的 Dao 层我们一般都会封装出一个通用的泛型 BaseDao,它可以实现对各种实体例如 User,Order 的基本 CRUD,然后具体的 UserDao,OrderDao 等等会去继承它,提供其他的 Dao 方法:

public class UserDao extends BaseDao<User>{}  

我们使用的 BaseDao 是基于 DBUtils 的,它需要实体的 Class 对象才能进行通用的查询方法,例如 User 的 Class 对象,我们可以通过构造函数,函数参数等手段传递给 BaseDao,但是有了反射,可以有更优雅的实现。

public class BaseDao<T> {
	
	private Class<T> clszz;
	
	public BaseDao(){
		Type type = this.getClass().getGenericSuperclass();//拿到带类型参数的泛型父类
		if(type instanceof ParameterizedType){//这个Type对象根据泛型声明,就有可能是4中接口之一,如果它是BaseDao<User>这种形式
			ParameterizedType parameterizedType = (ParameterizedType) type;
			Type[] actualTypeArguments = parameterizedType.getActualTypeArguments();//获取泛型的类型参数数组
			if(actualTypeArguments != null && actualTypeArguments.length == 1){
				if(actualTypeArguments[0] instanceof Class){//类型参数也有可能不是Class类型
					this.clszz = (Class<T>) actualTypeArguments[0];
				}else{
					//例如: BaseDao<BaseDao<User>>,获取到的就不是Class,而又是ParameterizedType,即嵌套的
					ParameterizedType,一层一层剥开,最终是可以得到User的Class对象的
				}
			}
		}
	}
	
	public T get(String sql,Object...params){
		QueryRunner qr = new QueryRunner();
		T obj;
		Connection connection;
		try {
			connection = JdbcUtil.getConnection();
			obj = qr.query(connection,sql,new BeanHandler<T>(clszz),params);
		} catch (SQLException e) {
			e.printStackTrace();
			return null;
		}
		return obj;
	}
}


  • Java

    Java 是一种可以撰写跨平台应用软件的面向对象的程序设计语言,是由 Sun Microsystems 公司于 1995 年 5 月推出的。Java 技术具有卓越的通用性、高效性、平台移植性和安全性。

    3194 引用 • 8214 回帖 • 3 关注
  • class
    4 引用 • 3 回帖 • 1 关注

相关帖子

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...

推荐标签 标签

  • 工具

    子曰:“工欲善其事,必先利其器。”

    295 引用 • 749 回帖
  • Ngui

    Ngui 是一个 GUI 的排版显示引擎和跨平台的 GUI 应用程序开发框架,基于
    Node.js / OpenGL。目标是在此基础上开发 GUI 应用程序可拥有开发 WEB 应用般简单与速度同时兼顾 Native 应用程序的性能与体验。

    7 引用 • 9 回帖 • 402 关注
  • 黑曜石

    黑曜石是一款强大的知识库工具,支持本地 Markdown 文件编辑,支持双向链接和关系图。

    A second brain, for you, forever.

    20 引用 • 193 回帖
  • SVN

    SVN 是 Subversion 的简称,是一个开放源代码的版本控制系统,相较于 RCS、CVS,它采用了分支管理系统,它的设计目标就是取代 CVS。

    29 引用 • 98 回帖 • 688 关注
  • 钉钉

    钉钉,专为中国企业打造的免费沟通协同多端平台, 阿里巴巴出品。

    15 引用 • 67 回帖 • 292 关注
  • 链书

    链书(Chainbook)是 B3log 开源社区提供的区块链纸质书交易平台,通过 B3T 实现共享激励与价值链。可将你的闲置书籍上架到链书,我们共同构建这个全新的交易平台,让闲置书籍继续发挥它的价值。

    链书社

    链书目前已经下线,也许以后还有计划重制上线。

    14 引用 • 257 回帖
  • Rust

    Rust 是一门赋予每个人构建可靠且高效软件能力的语言。Rust 由 Mozilla 开发,最早发布于 2014 年 9 月。

    58 引用 • 22 回帖 • 1 关注
  • 资讯

    资讯是用户因为及时地获得它并利用它而能够在相对短的时间内给自己带来价值的信息,资讯有时效性和地域性。

    56 引用 • 85 回帖
  • Wide

    Wide 是一款基于 Web 的 Go 语言 IDE。通过浏览器就可以进行 Go 开发,并有代码自动完成、查看表达式、编译反馈、Lint、实时结果输出等功能。

    欢迎访问我们运维的实例: https://wide.b3log.org

    30 引用 • 218 回帖 • 641 关注
  • 阿里巴巴

    阿里巴巴网络技术有限公司(简称:阿里巴巴集团)是以曾担任英语教师的马云为首的 18 人,于 1999 年在中国杭州创立,他们相信互联网能够创造公平的竞争环境,让小企业通过创新与科技扩展业务,并在参与国内或全球市场竞争时处于更有利的位置。

    43 引用 • 221 回帖 • 83 关注
  • C++

    C++ 是在 C 语言的基础上开发的一种通用编程语言,应用广泛。C++ 支持多种编程范式,面向对象编程、泛型编程和过程化编程。

    107 引用 • 153 回帖
  • OpenShift

    红帽提供的 PaaS 云,支持多种编程语言,为开发人员提供了更为灵活的框架、存储选择。

    14 引用 • 20 回帖 • 644 关注
  • Logseq

    Logseq 是一个隐私优先、开源的知识库工具。

    Logseq is a joyful, open-source outliner that works on top of local plain-text Markdown and Org-mode files. Use it to write, organize and share your thoughts, keep your to-do list, and build your own digital garden.

    6 引用 • 63 回帖 • 4 关注
  • 又拍云

    又拍云是国内领先的 CDN 服务提供商,国家工信部认证通过的“可信云”,乌云众测平台认证的“安全云”,为移动时代的创业者提供新一代的 CDN 加速服务。

    20 引用 • 37 回帖 • 566 关注
  • Thymeleaf

    Thymeleaf 是一款用于渲染 XML/XHTML/HTML5 内容的模板引擎。类似 Velocity、 FreeMarker 等,它也可以轻易的与 Spring 等 Web 框架进行集成作为 Web 应用的模板引擎。与其它模板引擎相比,Thymeleaf 最大的特点是能够直接在浏览器中打开并正确显示模板页面,而不需要启动整个 Web 应用。

    11 引用 • 19 回帖 • 383 关注
  • JVM

    JVM(Java Virtual Machine)Java 虚拟机是一个微型操作系统,有自己的硬件构架体系,还有相应的指令系统。能够识别 Java 独特的 .class 文件(字节码),能够将这些文件中的信息读取出来,使得 Java 程序只需要生成 Java 虚拟机上的字节码后就能在不同操作系统平台上进行运行。

    180 引用 • 120 回帖 • 3 关注
  • HBase

    HBase 是一个分布式的、面向列的开源数据库,该技术来源于 Fay Chang 所撰写的 Google 论文 “Bigtable:一个结构化数据的分布式存储系统”。就像 Bigtable 利用了 Google 文件系统所提供的分布式数据存储一样,HBase 在 Hadoop 之上提供了类似于 Bigtable 的能力。

    17 引用 • 6 回帖 • 70 关注
  • 一些有用的避坑指南。

    69 引用 • 93 回帖
  • ZooKeeper

    ZooKeeper 是一个分布式的,开放源码的分布式应用程序协调服务,是 Google 的 Chubby 一个开源的实现,是 Hadoop 和 HBase 的重要组件。它是一个为分布式应用提供一致性服务的软件,提供的功能包括:配置维护、域名服务、分布式同步、组服务等。

    59 引用 • 29 回帖 • 7 关注
  • 创业

    你比 99% 的人都优秀么?

    82 引用 • 1395 回帖
  • 大疆创新

    深圳市大疆创新科技有限公司(DJI-Innovations,简称 DJI),成立于 2006 年,是全球领先的无人飞行器控制系统及无人机解决方案的研发和生产商,客户遍布全球 100 多个国家。通过持续的创新,大疆致力于为无人机工业、行业用户以及专业航拍应用提供性能最强、体验最佳的革命性智能飞控产品和解决方案。

    2 引用 • 14 回帖 • 3 关注
  • C

    C 语言是一门通用计算机编程语言,应用广泛。C 语言的设计目标是提供一种能以简易的方式编译、处理低级存储器、产生少量的机器码以及不需要任何运行环境支持便能运行的编程语言。

    85 引用 • 165 回帖 • 6 关注
  • Caddy

    Caddy 是一款默认自动启用 HTTPS 的 HTTP/2 Web 服务器。

    12 引用 • 54 回帖 • 166 关注
  • 书籍

    宋真宗赵恒曾经说过:“书中自有黄金屋,书中自有颜如玉。”

    76 引用 • 389 回帖
  • V2EX

    V2EX 是创意工作者们的社区。这里目前汇聚了超过 400,000 名主要来自互联网行业、游戏行业和媒体行业的创意工作者。V2EX 希望能够成为创意工作者们的生活和事业的一部分。

    17 引用 • 236 回帖 • 285 关注
  • Tomcat

    Tomcat 最早是由 Sun Microsystems 开发的一个 Servlet 容器,在 1999 年被捐献给 ASF(Apache Software Foundation),隶属于 Jakarta 项目,现在已经独立为一个顶级项目。Tomcat 主要实现了 JavaEE 中的 Servlet、JSP 规范,同时也提供 HTTP 服务,是市场上非常流行的 Java Web 容器。

    162 引用 • 529 回帖 • 7 关注
  • Spring

    Spring 是一个开源框架,是于 2003 年兴起的一个轻量级的 Java 开发框架,由 Rod Johnson 在其著作《Expert One-On-One J2EE Development and Design》中阐述的部分理念和原型衍生而来。它是为了解决企业应用开发的复杂性而创建的。框架的主要优势之一就是其分层架构,分层架构允许使用者选择使用哪一个组件,同时为 JavaEE 应用程序开发提供集成的框架。

    945 引用 • 1460 回帖 • 1 关注