Annotations and reflection in Java (notes)

1. Notes

1. What is annotation?

  • Annotation is a new technology introduced starting from JDK5.0.
  • The role of Annotation: It is not the program itself, it can explain the program. Can be read by other programs (such as compilers, etc.).
  • Annotation format: The annotation is "@annotation name" that exists in the code, and some parameter values ​​can also be added.

2. Built-in annotations

  • @Override: used as a figure of speech to indicate that a method declaration intends to override another declaration in the superclass
  • @Deprecated: Deprecated, but it can be used, or a better way exists.
  • @SuppressWarnings: Used to suppress warning messages during compilation, parameters must be added.

//SuppressWarnings 用来抑制编译时的警告信息,必须要添加参数
@SuppressWarnings("all")
public class test1 extends parent{
    
    
    public static void main(String[] args) {
    
    
    }
    //Override 重写的注解
    @Override
    public void test1() {
    
    
        super.test1();
    }
    //Deprecated 不推荐使用,但是可以使用,或存在更好的方式。
    @Deprecated
    public static void test2(){
    
    
        System.out.println("这是Deprecated");}
}

3. Meta-annotation
The role of meta-annotation is to annotate other annotations. Java defines 4 standard meta-annotation types, which are used to
provide explanations for other annotation types.

  • @Target: used to describe the scope of use of annotations (ie: where the described annotations can be used)
  • @Retention: Indicates at what level the annotation information needs to be saved, used to describe the life cycle of the annotation (SOURCE < CLASS < RUNTIME)
  • @Document: indicates that the annotation will be included in javadoc
  • @Inherited: Indicates that subclasses can inherit this annotation from the parent class
public class Test2 {
    
    
    @MyAnnotation
    public void test(){
    
    

    }
}

//定义一个自己的注解
//Target 表示这个注解可以用在哪个地方
//Retention 表示我们注解在什么地方有效
//Inherited 子类可以继承父类的注解
@Target(value = {
    
    ElementType.METHOD,ElementType.ANNOTATION_TYPE})
//runtime>class>source
@Retention(value = RetentionPolicy.RUNTIME)
@Inherited
@interface  MyAnnotation{
    
    

}

4. Custom annotations

  • When using @interface custom annotation, the java.lang.annotation.Annotation interface is automatically inherited.
  • @interface is used to declare an annotation, format: public @interface annotation name {definition content}.
  • Each of these methods actually declares a configuration parameter.
  • The name of the method is the name of the parameter.
  • The return value type is the type of the parameter (the return value can only be basic types, Class, String, enum).
  • You can declare the default value of a parameter through default.
  • If there is only one parameter member, the parameter is generally named value.
  • Annotation elements must have values. When we define annotation elements, we often use empty strings and 0 as the default value.
public class Test3 {
    
    
    //注解可以显示赋值,如果没有默认值,我们就必须给注解赋值。
    @MyAnnotation2(age=23)
    public void test1(){
    
    

    }

}
@Target({
    
    ElementType.METHOD,ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@interface MyAnnotation2{
    
    
    //注解的参数:参数类型+参数名();
    String name() default "";
    int age();

}

2. Reflection

1. What is reflection?
Reflection means that we can load, detect, and use classes at runtime that are completely unknown during compilation. It is a dynamic mechanism that allows us to direct program instantiation, operate attributes, and call methods through strings. This makes the code more flexible, but it also brings more resource overhead.
After the class is loaded, a Class type object is generated in the heap memory (a class has only one Class object). This object contains the complete structural information of the class. We can see the structure of the class through this object. This object is like a mirror, through which we can see the structure of the class, so we vividly call it reflection.

2. How to obtain the reflected class?
First create a User entity class

@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
    
    
    private String id;
    public String name;
    private Integer age;
}

Obtained through three methods

//获取反射
public class Test1 {
    
    
    //通过Class.forName()获取(最常用)
    public static void main(String[] args) {
    
    
        try {
    
    
            Class aClass = Class.forName("com.example.dci.Reflect.pojo.User");
        } catch (ClassNotFoundException e) {
    
    
            e.printStackTrace();
        }
        //通过getClass()获取
        User  user = new User();
        Class aClass1 = user.getClass();

        //通过.class来获取
        Class<User> userClass = User.class;
    }
}

2. How to use reflection?

  • Get class names, variables, fields, and methods
public class Test2 {
    
    
    public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException {
    
    

        Class aClass = Class.forName("com.example.dci.Reflect.pojo.User");
        //获取全类名
        String name = aClass.getName();
        System.out.println(name);
        //获取简单类名
        String simpleName = aClass.getSimpleName();
        System.out.println(simpleName);
        //获取类的字段、某些变量
        //获取该类的所有public字段,包括父类的
        Field[] fields = aClass.getFields();
        for ( Field field: fields ){
    
    
            System.out.println(field.getName());
        }
        //根据字段名获取该类的public字段
        Field name1 = aClass.getField("name");
        //根据字段名获取该类的字段
        aClass.getDeclaredField("age");


    }
 Class aClass = Class.forName("com.example.dci.Reflect.pojo.User");
        //获取该类的所有public方法,包括父类的
        Method[] methods = aClass.getMethods();
        //根据方法名获取该类的public方法
        Method method = aClass.getMethod("getName");

        //如果该类为重写方法,可以在第二个参数加上重写方法的参数类型,不写为无参数的方法
        Method paramMethod = aClass.getMethod("getName",String.class);

        //获取该类的所有方法,不包括父类(仅自定义)
        Method[] declaredMethods = aClass.getDeclaredMethods();
        //根据方法名获取该类的方法
        Method declaredMethod = aClass.getDeclaredMethod("getName");
    }
  • Get the constructor of the class
//获取类的构造器
public class Test4 {
    
    
    public static void main(String[] args) throws Exception {
    
    

        Class aClass = Class.forName("com.example.dci.Reflect.pojo.User");
        //获取该类的所有构造器,包括父类
        Constructor[] constructors = aClass.getConstructors();

        //根据构造器的参数类型来获取指定构造器,不写为无参构造器
        Constructor constructor = aClass.getConstructor();
        Constructor constructor1 = aClass.getConstructor(String.class,int.class);

        //获取该类的所有构造器,不包括父类
        Constructor[] declaredConstructors = aClass.getDeclaredConstructors();

        //根据构造器的参数类型来获取指定的自定义构造器,不写为无参构造器
        Constructor declaredConstructor = aClass.getDeclaredConstructor();
        Constructor declaredConstructor1 = aClass.getDeclaredConstructor(String.class, int.class);

    }
}
  • Instantiate a class
//类的实例化
public class Test5 {
    
    
    public static void main(String[] args) throws Exception {
    
    

        Class aClass = Class.forName("com.example.dci.Reflect.pojo.User");
        //通过class类直接实例化,使用的是User类的无参构造器
        User user = (User) aClass.newInstance();
        //获取构造器来进行实例化,这里获取有参构造器
        Constructor declaredConstructor = aClass.getDeclaredConstructor(String.class,String.class,Integer.class);
        //根据构造器进行实例化
        User user1 = (User) declaredConstructor.newInstance("12", "admin",44);
        System.out.println(user1);
    }
}
  • operation result

Insert image description here

  • Use emission to call methods
public class Test6 {
    
    
    public static void main(String[] args) throws Exception{
    
    

        Class aClass = Class.forName("com.example.dci.Reflect.pojo.User");
        User user = (User) aClass.newInstance();
        Method setName = aClass.getMethod("setName", String.class);
        //第一个是调用底层方法的对象,也就是通过哪个对象来调用方法
        //第二个为可变参数,是用于方法调用的参数
        setName.invoke(user,"admin1");
        System.out.println(user);
    }
}
  • operation result
    Insert image description here
  • Use reflection to modify the value of a field (use id.setAccessible(true) to skip security checks)
public class Test7 {
    
    
    public static void main(String[] args) throws Exception{
    
    
        Class aClass = Class.forName("com.example.dci.Reflect.pojo.User");

        User o = (User) aClass.newInstance();
        Field id = aClass.getDeclaredField("id");
        //使用id.setAccessible(true)跳过安全检查
         id.setAccessible(true);
        //第一个参数为修改的字段的对象
        //第二个为被修改字段的新值
        id.set(o,"123");
        System.out.println(o);
    }
}
  • operation result
    Insert image description here

3. Use of annotations and reflection

  • The annotation is a custom annotation created previously
//定义一个自己的注解
//Target 表示这个注解可以用在哪个地方
//Retention 表示我们注解在什么地方有效
//Inherited 子类可以继承父类的注解
@Target(value = {
    
    ElementType.METHOD,ElementType.ANNOTATION_TYPE})
//runtime>class>source
@Retention(value = RetentionPolicy.RUNTIME)
@Inherited
public @interface  MyAnnotation{
    
    
     String name() default "";
}
  • To get the value of the annotation, first use reflection to get the class modified by the annotation, and then get the value of the annotation by calling ***getDeclaredAnnotation(annotation name.class)***.
//注解与反射
public class Test8 {
    
    

    public static void main(String[] args) throws Exception {
    
    
        Class aClass = Class.forName("com.example.dci.annotation.test1");
        Method test1 = aClass.getDeclaredMethod("test2");
        MyAnnotation declaredAnnotation = test1.getDeclaredAnnotation(MyAnnotation.class);
        String value = declaredAnnotation.name();
        System.out.println(value);


    }

}

Guess you like

Origin blog.csdn.net/lzfaq/article/details/122105249