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方法:

  1. public class UserDao extends BaseDao<User>{}

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

    1. public class BaseDao<T> {
    2. private Class<T> clszz;
    3. public BaseDao(){
    4. Type type = this.getClass().getGenericSuperclass();//拿到带类型参数的泛型父类
    5. if(type instanceof ParameterizedType){//这个Type对象根据泛型声明,就有可能是4中接口之一,如果它是BaseDao<User>这种形式
    6. ParameterizedType parameterizedType = (ParameterizedType) type;
    7. Type[] actualTypeArguments = parameterizedType.getActualTypeArguments();//获取泛型的类型参数数组
    8. if(actualTypeArguments != null && actualTypeArguments.length == 1){
    9. if(actualTypeArguments[0] instanceof Class){//类型参数也有可能不是Class类型
    10. this.clszz = (Class<T>) actualTypeArguments[0];
    11. }else{
    12. //例如: BaseDao<BaseDao<User>>,获取到的就不是Class,而又是ParameterizedType,即嵌套的
    13. ParameterizedType,一层一层剥开,最终是可以得到User的Class对象的
    14. }
    15. }
    16. }
    17. }
    18. public T get(String sql,Object...params){
    19. QueryRunner qr = new QueryRunner();
    20. T obj;
    21. Connection connection;
    22. try {
    23. connection = JdbcUtil.getConnection();
    24. obj = qr.query(connection,sql,new BeanHandler<T>(clszz),params);
    25. } catch (SQLException e) {
    26. e.printStackTrace();
    27. return null;
    28. }
    29. return obj;
    30. }
    31. }

Java泛型之Type体系的更多相关文章

  1. Java泛型type体系

    最近看开源代码,看到里面很多Java泛型,并且通过反射去获取泛型信息.如果说要看懂泛型代码,那还是比较容易,但是如果要自己利用泛型写成漂亮巧妙的框架,那必须对泛型有足够的了解.所以这两三天就不在不断地 ...

  2. 基础篇:深入解析JAVA泛型和Type类型体系

    目录 1 JAVA的Type类型体系 2 泛型的概念 3 泛型类和泛型方法的示例 4 类型擦除 5 参数化类型ParameterizedType 6 泛型的继承 7 泛型变量TypeVariable ...

  3. 转:有关Java泛型的类型擦除(type erasing)

    转载自:拈花微笑 自从Java 5引入泛型之后,Java与C++对于泛型不同的实现的优劣便一直是饭后的谈资.在我之前的很多training中,当讲到Java泛型时总是会和C++的实现比较,一般得出的结 ...

  4. Java泛型总结

    1. 什么是泛型?泛型(Generic type 或者 generics)是对 Java 语言的类型系统的一种扩展,以支持创建可以按类型进行参数化的类.可以把类型参数看作是使用参数化类型时指定的类型的 ...

  5. Java——泛型

    前言 一般的类和方法,使用的都是具体的类型:基本类型或者自定义的类.如果我们要编写出适用于多种类型的通用代码,那么肯定就不能使用具体的类型.前面我们介绍过多态,多态算是一种泛化机制,但是也会拘泥于继承 ...

  6. JDK 泛型之 Type

    JDK 泛型之 Type 一.Type 接口 JDK 1.5 引入 Type,主要是为了泛型,没有泛型的之前,只有所谓的原始类型.此时,所有的原始类型都通过字节码文件类 Class 类进行抽象.Cla ...

  7. Java中的Type

    Type是Java 编程语言中所有类型的公共高级接口(官方解释),也就是Java中所有类型的“爹”:其中,“所有类型”的描述尤为值得关注.它并不是我们平常工作中经常使用的 int.String.Lis ...

  8. Java基础学习总结(83)——Java泛型总结

    1. 什么是泛型? 泛型(Generic type 或者 generics)是对 Java 语言的类型系统的一种扩展,以支持创建可以按类型进行参数化的类.可以把类型参数看作是使用参数化类型时指定的类型 ...

  9. Java基础系列二:Java泛型

    该系列博文会告诉你如何从入门到进阶,一步步地学习Java基础知识,并上手进行实战,接着了解每个Java知识点背后的实现原理,更完整地了解整个Java技术体系,形成自己的知识框架. 一.泛型概述 1.定 ...

随机推荐

  1. Hankson 的趣味题

    题解: 硬是把一道傻逼题写到了200行.. 长长的模板就有70行.. 由于我没有做的时候觉得并不保证$a1|a0$ $b0|b1$ 然后就加了很多特判.. 我的做法就是暴力分解质因数 T*sqrt(n ...

  2. nginx proxy_pass指令’/’注意事项

    1. proxy_pass配置说明 不带/ location /test/ { proxy_pass http://t6:8300; } 带/ location /test/ { proxy_pass ...

  3. sparkStreaming消费kafka-1.0.1方式:direct方式(存储offset到zookeeper)

    版本声明: kafka:1.0.1 spark:2.1.0 注意:在使用过程中可能会出现servlet版本不兼容的问题,因此在导入maven的pom文件的时候,需要做适当的排除操作 <?xml ...

  4. JMeter学习笔记2-图形界面简单介绍

    废话少说直接干活的给: 一.打开和运行JMeter,出现UI界面.如图下所示: 工具栏:常见操作的图标集合,有New(新建), Template(模板) ,Save(保存),Start(开始) ,St ...

  5. appium---第三个脚本,进入评论页,发表评论

    #进入编辑页,点击编辑框,固定光标 #com.xxx.xxx:id/edit__content drive.find_element_by_id('/edit_content').click(); t ...

  6. scrapy下载图片报[scrapy.downloadermiddlewares.robotstxt] DEBUG: Forbidden by robots.txt:错误

    本文转自:http://blog.csdn.net/zzk1995/article/details/51628205 先说结论,关闭scrapy自带的ROBOTSTXT_OBEY功能,在setting ...

  7. day60 pymysql

    预知扩展内容,详见地址如下(关于数据库备份和恢复) http://www.cnblogs.com/linhaifeng/articles/7525619.html 我们一般写程序都是在py文件里面,那 ...

  8. 进程,线程,协程,io多路复用 总结

    并发:要做到同时服务多个客户端,有三种技术 1. 进程并行,只能开到当前cpu个数的进程,但能用来处理计算型任务 ,开销最大 2. 如果并行不必要,那么可以考虑用线程并发,单位开销比进程小很多 线程: ...

  9. python中sqlite问题和坑

    import sqlite3 #导入模块 conn = sqlite3.connect('example.db') C=conn.cursor() #创建表 C.execute('''CREATE T ...

  10. 【Excel】SUMIF 或用 筛选器 实现挑选含有某些字段的值,然后把这些值所对应的后面某列上的值相加

    Background: 挑选含有某些字段的值,然后把这些值所对应的后面某列上的值相加.比如挑选下表中,所有带有“MX104”这个字段的值,然后把它的后面total那一列的值相加. Solution: ...