Java泛型之Type体系
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<T>,List<String>,这些都叫参数化类型。得到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泛型之Type体系的更多相关文章
- Java泛型type体系
最近看开源代码,看到里面很多Java泛型,并且通过反射去获取泛型信息.如果说要看懂泛型代码,那还是比较容易,但是如果要自己利用泛型写成漂亮巧妙的框架,那必须对泛型有足够的了解.所以这两三天就不在不断地 ...
- 基础篇:深入解析JAVA泛型和Type类型体系
目录 1 JAVA的Type类型体系 2 泛型的概念 3 泛型类和泛型方法的示例 4 类型擦除 5 参数化类型ParameterizedType 6 泛型的继承 7 泛型变量TypeVariable ...
- 转:有关Java泛型的类型擦除(type erasing)
转载自:拈花微笑 自从Java 5引入泛型之后,Java与C++对于泛型不同的实现的优劣便一直是饭后的谈资.在我之前的很多training中,当讲到Java泛型时总是会和C++的实现比较,一般得出的结 ...
- Java泛型总结
1. 什么是泛型?泛型(Generic type 或者 generics)是对 Java 语言的类型系统的一种扩展,以支持创建可以按类型进行参数化的类.可以把类型参数看作是使用参数化类型时指定的类型的 ...
- Java——泛型
前言 一般的类和方法,使用的都是具体的类型:基本类型或者自定义的类.如果我们要编写出适用于多种类型的通用代码,那么肯定就不能使用具体的类型.前面我们介绍过多态,多态算是一种泛化机制,但是也会拘泥于继承 ...
- JDK 泛型之 Type
JDK 泛型之 Type 一.Type 接口 JDK 1.5 引入 Type,主要是为了泛型,没有泛型的之前,只有所谓的原始类型.此时,所有的原始类型都通过字节码文件类 Class 类进行抽象.Cla ...
- Java中的Type
Type是Java 编程语言中所有类型的公共高级接口(官方解释),也就是Java中所有类型的“爹”:其中,“所有类型”的描述尤为值得关注.它并不是我们平常工作中经常使用的 int.String.Lis ...
- Java基础学习总结(83)——Java泛型总结
1. 什么是泛型? 泛型(Generic type 或者 generics)是对 Java 语言的类型系统的一种扩展,以支持创建可以按类型进行参数化的类.可以把类型参数看作是使用参数化类型时指定的类型 ...
- Java基础系列二:Java泛型
该系列博文会告诉你如何从入门到进阶,一步步地学习Java基础知识,并上手进行实战,接着了解每个Java知识点背后的实现原理,更完整地了解整个Java技术体系,形成自己的知识框架. 一.泛型概述 1.定 ...
随机推荐
- 【回顾】html链接、头部
1.HTML 链接 HTML 使用超级链接与网络上的另一个文档相连.几乎可以在所有的网页中找到链接.点击链接可以从一张页面跳转到另一张页面. HTML 超链接(链接) HTML使用标签 <a&g ...
- 【NPM】常见问题解决
问题列表 问题一:npm install 执行报错 npm ERR! Unexpected end of JSON input while parsing near '...ependencies&q ...
- 【Android】Tips for Android developer: “Conversion to Dalvik format failed: Unable to execute dex: null”
Androiddeveloper, I have met a strange problem when I want use a third party jar, it remained me tha ...
- 向Spark集群提交任务
1.启动spark集群. 启动Hadoop集群 cd /usr/local/hadoop/ sbin/start-all.sh 启动Spark的Master节点和所有slaves节点 cd /usr/ ...
- js隐藏元素
js隐藏元素 $("#serviceType").css('display','none'); js显示元素 $("#serviceType3").css('d ...
- 环形链表(给定一个链表,返回链表开始入环的第一个节点。 如果链表无环,则返回 null)
思想: 思想:用快慢指针先判断是否有环,有环则 假设头结点到环入口距离为n,环入口到快慢指针相遇结点距离为m,则慢指针走的路程 为m+n,而快指针走的路程为m+n+k*l (k*l表示绕环走的路程), ...
- TCP、UDP和HTTP区别
http:是用于www浏览的一个协议.tcp:是机器之间建立连接用的到的一个协议. 1.TCP/IP是个协议组,可分为三个层次:网络层.传输层和应用层.在网络层有IP协议.ICMP协议.ARP协议.R ...
- GRNN/PNN:基于GRNN、PNN两神经网络实现并比较鸢尾花种类识别正确率、各个模型运行时间对比—Jason niu
load iris_data.mat P_train = []; T_train = []; P_test = []; T_test = []; for i = 1:3 temp_input = fe ...
- 生日蛋糕 POJ - 1190 (搜索+剪枝)
7月17日是Mr.W的生日,ACM-THU为此要制作一个体积为Nπ的M层生日蛋糕,每层都是一个圆柱体. 设从下往上数第i(1 <= i <= M)层蛋糕是半径为Ri, 高度为Hi的圆柱.当 ...
- win10安装Oracle11g,出现INS-13001环境不满足最低要求问题
今天安装Oracle11g,出现INS-13001环境不满足最低要求问题: 解决方法 在安装时点击setup.exe之后,出现了:[INS-13001]环境不满足最低要求 这时,打开你的解压后的dat ...