Java 基础-反射与注解

版权声明:本文为博博原创文章,未经博博允许不得转载。 https://blog.csdn.net/u013523377/article/details/72858621

一、Class

1. Class 类型的获取

  • Clazz.class;
  • clazz.getClass();
  • Class.forName(String className);

2. 根据 Class 类型创建类实例

Class clazzType = Clazz.class;

try{
    // Clazz 必需含有无参构造方法
    Clazz clazzBean = (Clazz)clazzType.newInstance();
}catch(Exception e){
    e.printStackTrace();
}

3. Class 加载

加载方式 实现 描述
静态加载 new Clazz() 在编译过程就加载
动态加载 (Class.forName(String className)).newInstance() 运行时才加载

二、反射

1. 反射的基本应用

class Clazz{
    public void print(String str){
        System.out.print("str");
    }
}
// 1. 获取类信息
Clazz clazz = new Clazz();
Class c = clazz.getClass();

try{
    // 2. 获取类方法
    Method m = c.getMethod("print", String.class);
    // 3. 实现方法的反射操作
    m.invoke(clazz, "设定输出内容");
}catch(Exception e){
    e.printStackTrace();
}   

2. 反射在泛型中的应用

反射操作位于编译之后,即编译后为泛型对象将失去泛型特征

ArrayList<String> list = new ArrayList<String>();
Class c = list.getClass();

try{
    // 通过反射绕过编译时对插入值类型的判断
    Method m = c.getMethod("add", Object.class);
    m.invoke(list, 1);
}catch(Exception e){
    e.printStackTrace();
}

三、注解

1. 概念理解

  • 成员类型必需是原始类型 及 String,Class, Annotation, Enumeration
  • 如果注解成员只有一个,则成员命名必需为 value(),在使用时可忽略成员名与赋值号(=)
  • 注解类可无成员对象,称之为标识注解


// 元注解
@Target({ElementType.METHOD,ElementType.TYPE}) // 作用域
@Retention(RetentionPolicy.RUNTIME) // 声明生命周期
@Inherited // 允许子类继承,且仅继承类注解
@Documented // 生成 javadoc 时包含注解信息

// 使用@interface 定义注解
public @interface Description{

    // 无参无异常的成员声明
    String sex();
    String author();

    // 成员的默认值声明
    int age() default 18;
}


作用域 描述
@Target(ElementType.TYPE) 接口、类、枚举、注解
@Target(ElementType.FIELD) 字段、枚举的常量
@Target(ElementType.METHOD) 方法
@Target(ElementType.PARAMETER) 方法参数
@Target(ElementType.CONSTRUCTOR) 构造函数
@Target(ElementType.LOCAL_VARIABLE) 局部变量
@Target(ElementType.ANNOTATION_TYPE) 注解
@Target(ElementType.PACKAGE)


生命周期/注解分类 描述
@Retention(RetentionPolicy.SOURCE) 源码注解(仅源码中存在,编译后不存在)
@Retention(RetentionPolicy.CLASS) 编译时注解(源码与编译后均存在)
@Retention(RetentionPolicy.RUNTIME) 运行时注解(运行时存在,影响逻辑处理)

2. 自定义

语法: @<注解名>(<成员名1>=<成员值>,<成员名2>=<成员值2>,…)

@Description(sex="I am boy", author="gzejia",age="25")
public class Clazz{

    @Description(sex="I am boy", author="gzejia",age="25")
    public String manSex(){
        return "boy";
    }
}

3. 注解解析

通过反射获取类、函数或成员上的运行时注解信息,从而实现动态控制程序运行的逻辑

try{
    // 1.使用类加载器加载类
    Class c = Class.forName("...Clazz");

    // 2.判断是否存在注解信息
    boolean isExist = c.isAnnotationPresent(Description.class);

    // 3.获取类注解信息
    if(isExist){
        Description d = (Description)c.getAnnotation(Description.class);
        System.out.println(d.sex());
    }

    // 4.获取方法注解信息
    Method[] ms = c.getMethods();
    for(Method m : ms){
        boolean isMExist = m.isAnnotationPresent(Description.class);

        if(isExist){
            Description d = (Description)m.getAnnotation(Description.class);
            System.out.println(d.author());
        }
    }

    // 获取注解信息方式二(以获取方法注解信息为例)
    for(Method m : ms){
        Annotation[] as = m.getAnnotations();

        for(Annotation a : as){
            if(a instanceof Description){
                Description d = (Description)a;
                System.out.println(String.valueOf(d.age()));
            }
        }
    }
}catch(Exception e){
    e.printStackTrace();
}

[感谢慕课平台]

猜你喜欢

转载自blog.csdn.net/u013523377/article/details/72858621