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     }

 

原文地址:https://www.cnblogs.com/niujifei/p/14902755.html