zoukankan      html  css  js  c++  java
  • 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,比如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方法:

    [java] view plain copy
     
    1. public class UserDao extends BaseDao<User>{}  


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

    [java] view plain copy
     
      1. public class BaseDao<T> {  
      2.       
      3.     private Class<T> clszz;  
      4.       
      5.     public BaseDao(){  
      6.         Type type = this.getClass().getGenericSuperclass();//拿到带类型参数的泛型父类  
      7.         if(type instanceof ParameterizedType){//这个Type对象根据泛型声明,就有可能是4中接口之一,如果它是BaseDao<User>这种形式  
      8.             ParameterizedType parameterizedType = (ParameterizedType) type;  
      9.             Type[] actualTypeArguments = parameterizedType.getActualTypeArguments();//获取泛型的类型参数数组  
      10.             if(actualTypeArguments != null && actualTypeArguments.length == 1){  
      11.                 if(actualTypeArguments[0] instanceof Class){//类型参数也有可能不是Class类型  
      12.                     this.clszz = (Class<T>) actualTypeArguments[0];  
      13.                 }else{  
      14.                     //例如: BaseDao<BaseDao<User>>,获取到的就不是Class,而又是ParameterizedType,即嵌套的  
      15.                     ParameterizedType,一层一层剥开,最终是可以得到User的Class对象的  
      16.                 }  
      17.             }  
      18.         }  
      19.     }  
      20.       
      21.     public T get(String sql,Object...params){  
      22.         QueryRunner qr = new QueryRunner();  
      23.         T obj;  
      24.         Connection connection;  
      25.         try {  
      26.             connection = JdbcUtil.getConnection();  
      27.             obj = qr.query(connection,sql,new BeanHandler<T>(clszz),params);  
      28.         } catch (SQLException e) {  
      29.             e.printStackTrace();  
      30.             return null;  
      31.         }  
      32.         return obj;  
      33.     }  
      34. }  
  • 相关阅读:
    WPF 关于拖拽打开文件的注意事项
    asp.net core 3.1中对Mongodb BsonDocument的序列化和反序列化支持
    用百度webuploader分片上传大文件
    多线程学习笔记
    web.config数据库连接字符串加密
    Visual Studio 2010 常用快捷方式
    Team Foundation Server 2013 日常使用使用手册(四)分支与合并
    Team Foundation Server 2013 日常使用使用手册(三)上传新工程、创建任务、创建bug、设置预警
    Team Foundation Server 2013 日常使用使用手册(二)修改、签入、撤销、回滚、对比代码变更
    Team Foundation Server 2013 日常使用使用手册(一)-本地连接TFS、查看任务
  • 原文地址:https://www.cnblogs.com/hyl8218/p/8398846.html
Copyright © 2011-2022 走看看