反射与注解

当我们不知道类是否加了set/get方法,但又希望能够得到它里面的一些属性或方法的时候,需要通过反射来获取,下面我创建了一个student类,但是我没有加set和get方法:

public class Student {
    private Integer id;
    private String name;
    private String pass;
    public String phone;
}

反射:先获得类,通过类.getInstance,得到对象,通过类名.getFileds可以得到类里面共有属性,如果要访问私有的,可以类名.getDeclaredFileds,可以得到类里面所有的私有属性,如果对属性赋值,需要先将可访问属性改为true,然后再利用set方法来进行赋值,详情操作见下:

Class<Student> studentClass = Student.class;//创建类
Student student = studentClass.newInstance();//创建对象
Field[] declaredFields = studentClass.getDeclaredFields();//得到全部属性
declaredFields[3].setAccessible(true);//开启访问权限
declaredFields[3].set(student,"10010");
System.out.println(student);

得到类的三种方式:

  1. 通过类名获得:
Class<Student> studentClass = Student.class;
  1. 通过对象获得:
Student student=new Student();
Class<? extends Student> aClass = student.getClass();
  1. 通过类的路径获得
Class<?> aClass1 = Class.forName("com.study.bean.Student");//但是这里有个泛型,如果直接创建对象会显示object

得到类之后得到属性的四种方法:

Field getDeclaredField(String name) 
返回一个Field对象,得到指定已声明字段 
Field[] getDeclaredFields() 返回的是Field数组,返回已声明的全部字段
    
Field getField(String name) 
返回一个Field对象,得到指定公共成员字段   
Field[] getFields() 返回的是Field数组,返回公共的全部字段

得到对象的方法:(在这里不是直接new)这里默认调用类的无参构造,如果没有无参构造会报异常:NoSuchMethodException

T newInstance() 

获取构造方法:

aClass1.getConstructors()

利用对象来赋值:

void set(Object obj, Object value) 

方法也是一样的方式来获取和访问:

//上面有泛型,下面需要强制转化
Student student1 = (Student) aClass1.newInstance();
Field[] declaredFields = aClass1.getDeclaredFields();

//得到类里面的公共方法:
Method setId = aClass1.getMethod("setId", Integer.class);
//赋值
setId.invoke(student1,3627);
Method getId = aClass1.getDeclaredMethod("getId");
//取值
System.out.println(getId.invoke(student1));

//得到类里面的私有方法:
Method show = aClass1.getDeclaredMethod("show", Integer.class, String.class, String.class, String.class);
//先打开权限
show.setAccessible(true);
//调用方法
show.invoke(student1, 23, "liku", "password", "1008611");

注解:

@Deprecated:标记该方法已过时

@SuppresWarning:消除编译器的警告💡

元注解:给注解加注解:

@Target:表示该注解修饰的数据类型范围

@Retention:表示该字段保留时间长短,一共有三个值:source<package<runtime

在反射中,利用getAnnotation映射获取的注解只能获取运行时的注解,其他两种注解拿不到,当非要去获取的时候返回的将会是空值

Method show = aClass1.getDeclaredMethod("show", Integer.class, String.class, String.class, String.class);
//先打开权限
show.setAccessible(true);
//调用方法
show.invoke(student1, 23, "liku", "password", "1008611");
//获取注解:
Override annotation = show.getAnnotation(Override.class);
System.out.println("注解:"+annotation);//null

对于注解里面的属性,有默认值的可以赋值,也可以不赋值

自定义注解:关键字:@interface

/**
 * 表示该注解只在构造,方法,类,接口,枚举才可使用
 */
@Target({ElementType.CONSTRUCTOR, ElementType.METHOD, ElementType.TYPE})
/**
 * 表示该注解只在运行时生效
 */
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation {
    /**
     * 属性
     *
     * @return
     */
    int a();

    /**
     * 属性
     *
     * @return
     */
    String b();

    /**
     * 属性
     *
     * @return
     */
    String[] c() default {};
}

写好之后,再在上面的student类中用我们的自定义注解:

//使用的时候需要对注解里面的属性赋值
@MyAnnotation(a=23,b="world")
public class Student {
    //这里的注解我没有修改默认值
@MyAnnotation(a = 3627, b = "liku")
private void show(Integer id, String name, String pass, String phone) {
    System.out.println(id + "  " + name + "  " + pass + "  " + phone);
}
//这里的注解我将注解里面的默认值修改为默认值
@MyAnnotation(a = 12, b = "hello", c = {"默认值"})
public Student(Integer id, String name, String pass, String phone) {
    this.id = id;
    this.name = name;
    this.pass = pass;
    this.phone = phone;
}
}

然后最后再通过反射来获取我们的自定义注解:

@SneakyThrows
private static void demo3() {
    Class<?> aClass1 = Class.forName("com.study.bean.Student");
    /**
     * 获取类的注解
     */
    MyAnnotation annotation = aClass1.getAnnotation(MyAnnotation.class);
    System.out.println(annotation);
    /**
     * 获取构造方法的注解
     */
    MyAnnotation annotation1 = aClass1.getConstructor().getAnnotation(MyAnnotation.class);
    System.out.println(annotation1);
    /**
     * 获取私有方法的注解
     * 需要开启访问权限
     */
    Method show = aClass1.getMethod("show");
    show.setAccessible(true);
    MyAnnotation showAnnotation = show.getAnnotation(MyAnnotation.class);
    System.out.println(showAnnotation);
}
posted @ 2022-12-04 11:58  Liku007  阅读(20)  评论(0编辑  收藏  举报