• What are annotations?

Java annotations, also known as Java annotations, is an Annotation mechanism introduced in JDK5.0. For example, common @override and @Deprecated are annotations. Annotations can be added to classes, methods, member variables, etc., in a manner of “tagging” them.

  • How are annotations defined?

Public @interface {} looks similar to the interface definition except for the @ symbol: public interface interface name annotation: public @interface annotation name

public @interface lkx {
    
}
Copy the code
  • How are annotations used?

For example, we can define “class, member variable, member method” as follows:

@lkx
public class Test {
    @lkx
    private int num;
    
    @lkx
    public static void main(String[] args) {
        System.out.println("hello"); }}Copy the code
  • Think about it

Now that the annotation is defined and used, I don’t want to define it on the class or on the member methods, I just want to define it on the member methods. How can I make the annotation only define it on the method, and get an error if it is defined elsewhere?Desired effect:

This is where meta-annotations are used to limit the scope.

  • Yuan notes

A meta-annotation is an annotation defined on an annotation. There are four meta-annotations in Java: @target @Retention @Documented @inherited

  • @Target

The @target is used to describe the scope of the definition of an annotation and to limit the types of elements defined by the annotation.

parameter role
ElementType.ANNOTATION_TYPE Can be applied to annotation types
ElementType.CONSTRUCTOR Can be applied to constructors
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 a method
ElementType.TYPE Can be applied to any element of a class

Since we want to restrict definitions to only member variables, we should use elementType.field

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

}
Copy the code

But what if we want to define both member variables and member methods? Multiple arguments need only be enclosed in curly braces and separated by commas

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

}
Copy the code

Now only the annotations defined on the class report errors

  • @Retention

@Retention is used to define the lifetime of annotations, which can also be interpreted as how they are stored.

parameter role
RetentionPolicy.SOURCE The annotations for the tag remain only at the source level and are ignored by the compiler
RetentionPolicy.CLASS The annotations for the tag are retained by the compiler at compile time, but ignored by the Java Virtual Machine (JVM)
RetentionPolicy.RUNTIME The annotations for the tag are retained by the JVM, so the runtime environment can use it

The following two meta-annotations are not used much and will not be explained in detail

  • @Documented

The @Documented is used to describe whether to retain the annotation information for the help document when it is generated.

  • @Inherited

@inherited is used to describe whether the note it decorates is Inherited.

  • Annotation element

Above we just defined an annotation, but it does not pass any information, it is just a tag. Now let’s see how to define parameters for an annotation:

@Target({ElementType.FIELD,ElementType.METHOD})
@Retention(RetentionPolicy.SOURCE)
public @interface lkx {
    String name(a) default"Zhang"; // You can use default to define a default value
    int age(a);
}
Copy the code

Now let’s look at how to pass parameters:

public class Test {

    // Name has a default value
    @lkx(name = "@lkx ",age = 18)
    private int num;
    
    public static void main(String[] args) {
        System.out.println("hello"); }}Copy the code
  • In actual combat

Now that the annotations are defined and the parameters are passed in, you are wondering what the annotations are for… Now we have a small requirement to assign the parameter passed in the annotation to the member variable. Such as:

@lkx(name = "@lkx ",age = 18)
private int num; //num is not assigned and is equal to 0Num = after the assignment18
Copy the code

Notes:

  1. The following code needs to use reflection, if you don’t know it, you can read my previous articles.
  2. Since we need to use reflection to get annotations, @Retention needs to be defined as retentionPolicy.runtime

Implementation code:

@Target({ElementType.FIELD,ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface lkx {
    String name(a) default"Zhang";
    int age(a);
}
Copy the code
public class Test {

    // Name has a default value
    @lkx(name = "@lkx ",age = 18)
    private static int num;

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

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

        // Get the bytecode of the class
        Class<Test> testClass = Test.class;
        // Get all member variables
        for (Field declaredField : testClass.getDeclaredFields()) {
            // Check for @lkx annotation on the member variable
            if (declaredField.isAnnotationPresent(lkx.class)) {
                lkx annotation = declaredField.getAnnotation(lkx.class);
                // Get the value of age in the annotation
                int age = annotation.age();
                declaredField.set(testClass.newInstance(),age);
            }
        }

        System.out.println("Num:" + num+" age: "+age); }}Copy the code

Running result:

Before assignment: num:0   age: 0Value: num:18   age: 38
Copy the code
  • thinking

If you are a friend of Android development, do you think the actual combat is familiar? If this doesn’t look familiar, look at the following code:

@BindView(R.id.groupChat)
Button mGroupChat;

@BindView(R.id.privateChat)
Button mPrivateChat;
Copy the code

With this in mind, you should be able to easily write a dynamic findViewById framework with annotations. However, it is not recommended to use it in projects because reflection can affect code execution efficiency. If you want to do this efficiently, I recommend to see how the Butterknife framework source code is implemented.