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. }  
  • 相关阅读:
    插入节点方法appendChild和insertBefore
    大河剧《独眼龙政宗》梵天丸喜多对话台词
    ie6绝对定位层元素消失
    strtok函数相关理解
    [创建型模式] Prototype
    用C实现旋转棒进度条指示器
    使用不规则数组(ragged array)和agetline()将整个文件读入内存
    [创建型模式] AbstractFactory
    xcode_4_and_ios_sdk_4.3__final相关下载地址
    [创建型模式] Singleton
  • 原文地址:https://www.cnblogs.com/hyl8218/p/8398846.html
Copyright © 2011-2022 走看看