JAVA注解,泛型,反射

一、注解

元注解

元注解是用来修饰注解的注解,java提供了3种元注解。

  • @Retention
    RetentionPolicy.SOURCE
    表明注解仅存在源码之中,不存在.class文件中,更不能运行时可见。常见的注解为@Override, @SuppressWarnings等。
    RetentionPolicy.CLASS
    这是默认的注解保留策略。这种策略下,注解将存在于.class文件中,但是不能被运行时访问。通常这种注解策略用来处理一些字节码级别的操作。
    RetentionPolicy.RUNTIME
    这种策略下可以被运行时访问到。通常情况下,我们都会结合反射来做一些事情。
  • @Target
    注解修饰的位置
  • @Inherited
    注解是否可以被子类继承
自定义注解

如下定义了一个MyAnnotation注解

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE,ElementType.FIELD})
@Inherited
public @interface MyAnnotation {
    
    String name();
    
    String value() default "";
    
}

二、泛型

Java采用泛型擦除机制来引入泛型。Java中的泛型仅仅是给编译器Javac使用的,确保数据的安全性和免去强制类型转换的麻烦。但是编译一旦完成,所有和泛型有关的类型全部被擦除。类型擦除机制存在的原因正是因为如果在运行时存在泛型,那么将要修改JVM指令集,这是非常致命的。
原始类型会生成字节码文件对象,而泛型类型相关的类型并不会生成与其相对应的字节码文件(因为泛型类型将会被擦除),因此,无法将泛型相关的新类型与class相统一。因此,为了程序的扩展性以及为了开发需要去反射操作这些类型,就引入了Type这个类型,并且新增了ParameterizedType, TypeVariable, GenericArrayType, WildcardType四个表示泛型相关的类型,再加上Class,这样就可以用Type类型的参数来接受以上五种子类的实参或者返回值类型就是Type类型的参数。统一了与泛型有关的类型和原始类型Class。而且这样一来,我们也可以通过反射获取泛型类型参数。
tips:

  • ParameterizedType:参数化类型,比如List<>。
  • GenericArrayType:泛型数组类型,比如比如List<>[],T[]这种。
  • TypeVariable:泛型变量,泛型信息在编译时会被转换为一个特定的类型, 而TypeVariable就是用来反映在编译前该泛型的信息。即我们常用的T,K这种泛型变量。
  • WildcardType:通配符类型,比如?、? extends Number、? super Integer。

三、反射获取注解,泛型信息

通过反射获取类,方法,参数里面的注解和泛型信息,示例如下。

@MyAnnotation(name = "zhangsan")
public class User {
    private String name;

    public void sayHi() {
        System.out.println("hi:i am " + name);
    }
    public void sayHi(String age,T t) {
        System.out.println("i am "+ name + ",and i am " + age + "year old,and t is"+ t);
    }

    public static void main(String[] args) throws Exception {
        Class clazz = User.class;
        /**
         * 获取类模板信息
         */
        // 获取自有属性
        Field[] fields = clazz.getDeclaredFields();
        // 获取自有方法
        Method[] methods = clazz.getDeclaredMethods();
        // 获取构造器
        Constructor[] constructors = clazz.getDeclaredConstructors();
        /**
         * 执行方法,修改属性
         */
        // 新建对象
        Constructor constructor = clazz.getDeclaredConstructor();
        User xiaoming = constructor.newInstance();
        // 修改属性
        Field field = clazz.getDeclaredField("name");// public的属性
        field.setAccessible(true);
        field.set(xiaoming, "xiaoming");
        field.setAccessible(false);
        // 调用方法
        Method method = clazz.getDeclaredMethod("sayHi", null);
        method.invoke(xiaoming, new Class[] {});
        /**
         * 获取注解
         */
        //获取修饰类的注解
        Annotation[] annotations = clazz.getAnnotations();
        /**
         * 获取泛型信息
         */
        //获取方法参数的泛型信息
        Method tMethod = clazz.getDeclaredMethod("sayHi",new Class[]{String.class,Object.class});
        Type[] types = tMethod.getGenericParameterTypes();
        for (Type type : types) {
            System.out.println(type.getTypeName());
            if (type instanceof TypeVariable) {
                TypeVariable typeVariable = (TypeVariable) type;
                System.out.println("TypeVariable:"+typeVariable.getName());
            }
        }
    }
}

你可能感兴趣的:(JAVA注解,泛型,反射)