[Java Basics] Annotations - Custom Annotations

What are annotations?

Java annotation (Annotation), also known as Java annotation, is an annotation mechanism introduced by JDK5.0. For example, our common @Override and @Deprecated are both annotations. Annotations can be added to classes, methods, member variables, etc., similar to " labeling " them.

How are annotations defined?

The public @interface annotation name {} looks very similar to the definition interface, except that there is an additional @ symbol interface: public interface interface name annotation: public @interface annotation name

public @interface lkx {
    
    
    
}

How to use annotations?

Now that our annotations have been defined, we can directly use "@ annotation name" when using them. For example, we can define them on " classes, member variables, and member methods " as follows:

@lkx
public class Test {
    
    
    @lkx
    private int num;
    
    @lkx
    public static void main(String[] args) {
    
    
        System.out.println("hello");
    }
}
  • think for a while

Now that the annotation has been defined and used, but I don’t want to define it on the class or member method, I just want to define it on the member method. How can I make the annotation only defined on the method and report an error when it is defined elsewhere? The desired effect: insert image description here

At this time, it is necessary to use meta annotations to limit the scope.

meta annotation

In layman's terms, meta-annotations are annotations defined on annotations . There are four meta-annotations in Java @Target @Retention @Documented @Inherited

@Target

@Target is used to describe the definition scope of the annotation, which can limit the element type defined by this annotation.

parameter effect
ElementType.ANNOTATION_TYPE Can be applied to annotation types
ElementType.CONSTRUCTOR can be applied to the constructor
ElementType.FIELD Can be applied to fields or properties
ElementType.LOCAL_VARIABLE can be applied to local variables
ElementType.METHOD Can be applied to method-level annotations
ElementType.PACKAGE Can be applied to package declarations
ElementType.PARAMETER parameters that can be applied to methods
ElementType.TYPE Can be applied to any element of the class

Because we want to restrict only to member variables, we should use ElementType.FIELD

@Target(ElementType.FIELD)
public @interface lkx {
    
    

}

But what should we do if we want to define both member variables and member methods at the same time? Multiple parameters only need to be wrapped in braces and separated by commas

@Target({
    
    ElementType.FIELD,ElementType.METHOD})
public @interface lkx {
    
    

}

Now only the annotations defined on the class report an errorinsert image description here

@Retention

@Retention is used to define the life cycle of annotations , and can also be understood as a storage method.

parameter effect
RetentionPolicy.SOURCE Marked annotations are kept only at the source level and are ignored by the compiler
RetentionPolicy.CLASS Marked annotations are preserved by the compiler at compile time, but ignored by the Java Virtual Machine (JVM)
RetentionPolicy.RUNTIME Marked annotations are preserved by the JVM, so the runtime environment can use it

The following two meta-annotations are not used much, so I will not explain them in detail for the time being

@Documented

@Documented is used to describe whether to retain its annotation information when generating help documents.

@Inherited

@Inherited is used to describe whether the annotation modified by it is inherited.

annotation element

We just defined an annotation above, but we can't pass any information, it's just equivalent to a label. Now let's see how to define parameters for the annotation:

@Target({
    
    ElementType.FIELD,ElementType.METHOD})
@Retention(RetentionPolicy.SOURCE)
public @interface lkx {
    
    
    String name() default "张三"; //可以使用default定义默认的值
    int age();
}

Now let's see how to pass parameters:

public class Test {
    
    

    //name有默认值,也可以不写
    @lkx(name = "李四",age = 18)
    private int num;
    
    public static void main(String[] args) {
    
    
        System.out.println("hello");
    }
}

combat

Now that the annotations are defined and the parameters are passed in, do you still wonder what the annotations are useful for? . . Now we have a small requirement to assign the parameters passed in the annotation to the member variables. For example:

@lkx(name = "李四",age = 18)
private int num; //num没有被赋值,等于0

赋值完成后
num = 18

Precautions:

  1. The following code needs to use reflection. If you don’t know how to do it, you can read my previous articles.
  2. Because you need to use reflection to get annotation parameters, @Retention needs to be defined as RetentionPolicy.RUNTIME

Implementation code:

@Target({
    
    ElementType.FIELD,ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface lkx {
    
    
    String name() default "张三";
    int age();
}
java复制代码public class Test {
    
    

    //name有默认值,也可以不写
    @lkx(name = "李四",age = 18)
    private static int num;

    @lkx(name = "王五",age = 38)
    private static int age;

    public static void main(String[] args) throws InstantiationException, IllegalAccessException {
    
    
        System.out.println("赋值前: num: " + num+"   age: "+age);

        //拿到类的字节码
        Class<Test> testClass = Test.class;
        //拿到所有成员变量
        for (Field declaredField : testClass.getDeclaredFields()) {
    
    
            //检测成员变量上是否有@lkx注解
            if (declaredField.isAnnotationPresent(lkx.class)) {
    
    
                lkx annotation = declaredField.getAnnotation(lkx.class);
                //获取到注解中的age的值
                int age = annotation.age();
                declaredField.set(testClass.newInstance(),age);
            }
        }

        System.out.println("赋值后: num: " + num+"   age: "+age);
    }
}

operation result:

java复制代码赋值前: num: 0   age: 0
赋值后: num: 18   age: 38

Guess you like

Origin blog.csdn.net/weixin_50799082/article/details/131236558