zoukankan      html  css  js  c++  java
  • Java 反射机制:(十三)获取运行时类的注解和泛型信息

    一、获取注解信息

      1、关于注解

        一个完整的注解,有三个要素:

        (1)声明

        (2)使用

        (3)读取

        像@Override,@SuppressWarings,@Deprecated等这些是JRE中声明的,也是由编译器读取的

        像@Test,@Before...等这些注解是JUnit声明和读取的

        像@author,@param...等这些注解是JRE中声明的,由javadoc.exe读取的

        对于自定义的注解,声明和读取需要自己完成

      2、声明注解

        自定义注解

        Demo:

    1 //声明注解
    2 @Target({TYPE,FIELD})
    3 @Retention(RetentionPolicy.RUNTIME)//只有生命周期是运行时,那么才可以被反射读取
    4 @interface MyAnnotation{
    5     String value();  //如果配置参数只有一个,名称是value,在使用时,赋值的话就可以省略"value="
    6     String name();   // 也可以使用 default 给它们指定默认值
    7 }

      3、使用注解

        Demo:使用自定义的注解

    1 //使用注解
    2 @MyAnnotation(value = "Annotation",name="Java")
    3 class MyClass{
    4     @MyAnnotation(value="String",name="Field")
    5     private String info;
    6 
    7 }

      4、读取注解

         主要分为三步:

          ① 获取 Class 对象

          ② 获取注解对象

          ③ 获取注解的配置参数的值

         Demo:

     1 public class TestAnnotation {
     2     @SuppressWarnings("unchecked")
     3     @Test
     4     public void test01() {
     5         //(1)获取Class对象
     6         Class clazz = MyClass.class;//四种方式之一
     7         
     8         //(2)获取注解对象
     9         MyAnnotation annotation = (MyAnnotation) clazz.getAnnotation(MyAnnotation.class);
    10         
    11         //(3)获取注解的配置参数的值
    12         String value = annotation.value();
    13         System.out.println("value = " + value);
    14         
    15         String name = annotation.name();
    16         System.out.println("name =" + name);
    17     }
    18     
    19     @SuppressWarnings("unchecked")
    20     @Test
    21     public void test02() throws NoSuchFieldException, SecurityException {
    22         //(1)获取Class对象
    23         Class clazz = MyClass.class;//四种方式之一
    24         
    25         //(2)获取属性对象
    26         Field infoField = clazz.getDeclaredField("info");
    27         
    28         //(3)获取注解对象
    29         MyAnnotation annotation = (MyAnnotation) infoField.getAnnotation(MyAnnotation.class);
    30         
    31         //(3)获取注解的配置参数的值
    32         String value = annotation.value();
    33         System.out.println("value = " + value);
    34         
    35         String name = annotation.name();
    36         System.out.println("name =" + name);
    37     }
    38     
    39 }

    二、获取泛型信息

      1、读取泛型

        读取某个类的泛型实参主要分为三步:

        (1)获取 Class 对象

        (2)获取泛型父类

    Type type = clazz.getGenericSuperclass();
    ParameterizedType type = (ParameterizedType) clazz.getGenericSuperclass();

        (3)获取类型实参

          ① Type:代表Java的所有类型

          ② Class:代表的是普通的类型,没有泛型信息的

          ③ ParameterizedType:参数化类型    例如:Father<Integer, String>

          ④ GenericArrayType:泛型数组类型   例如:T[]

          ⑤ TypeVariable:类型变量    例如:T

          ⑥ WildcardType:带?通配符的泛型的类型  例如:ArrayList<?>  或ArrayList<? super 下限> 或ArrayList<? extends 上限>

      2、案例

     1 //泛型类型形参:<T,U>
     2 class Father<T,U>{
     3     
     4 }
     5 //泛型类型实参:<Integer, String>
     6 class Son extends Father<Integer, String>{
     7     
     8 }
     9 
    10   @Test
    11     public void test01() {
    12         //获取Son类的泛型父类的类型实参
    13         //(1)获取Class对象
    14         Class clazz = Son.class;
    15         
    16         //(2)获取泛型父类
    17         //获取普通父类
    18 //        Class fu = clazz.getSuperclass();
    19 //        System.out.println(fu);
    20         
    21         //获取泛型父类的参数
    22         ParameterizedType type = (ParameterizedType) clazz.getGenericSuperclass();
    23         
    24         //(3)获取类型实参
    25         Type[] types = type.getActualTypeArguments();
    26         for (Type t : types) {
    27             System.out.println(t);
    28         }
    29     }

        对于泛型类、接口的类型形参,什么时候才能确定具体的类型呢?

    (1)创建它的对象

    (2)继承泛型类

    (3)实现泛型接口

        Demo:

     1 class Tools<T>{
     2     private Class type;
     3     
     4     public Tools() {
     5         //在创建子类对象时,来确定type的代表类型
     6         //(1)获取正在new的对象的类型Class对象
     7         Class clazz = this.getClass();
     8         
     9         //(2)获取泛型父类的信息
    10         ParameterizedType t = (ParameterizedType) clazz.getGenericSuperclass();
    11         
    12         //(3)获取类型实参
    13         type = (Class) t.getActualTypeArguments()[0];
    14     }
    15 
    16 
    17     public void test(){
    18         //这个方法中需要用到T的类型对象,即T的Class对象
    19 //        Class c = T.class;//此时无法确定T的类型
    20         System.out.println(type);
    21     }
    22     
    23 }
    24 class MyTools extends Tools<String>{
    25     
    26 }
    27 
    28 @Test
    29     public void test02() {
    30         MyTools my = new MyTools();
    31         my.test();   //class java.lang.String
    32         
    33     }

     

  • 相关阅读:
    hdu1754:I Hate It
    hdu1166
    bzoj1642:挤奶时间
    线段树
    bzoj1699:排队
    bzoj3438: 小M的作物
    bzoj2127: happiness
    bzoj2768[JLOI2010]冠军调查
    bzoj1070[SCOI2007]修车
    bzoj1305[CQOI2009]dance跳舞
  • 原文地址:https://www.cnblogs.com/niujifei/p/14902755.html
Copyright © 2011-2022 走看看