A preface

I’m sure we’ve come across annotations all over the place. Common frameworks such as Butterknife, Retrofit, ARouter, and so on have all been annotated, so I’m sure you’ll all be searching for annotations. Here is a Demo to see the use of custom annotations.

Ii. Knowledge Preparation

Our most common annotation is @Override, so let’s take a look at the code for this annotation.

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.SOURCE)
public @interface Override {
}Copy the code

All right, so let’s just look at the declaration at sign interface at first glance it might look like it’s interface but there’s an at sign there and that’s the key word that you’re going to use to declare your annotations, so you just have to remember that. I don’t have any definitions in the curly braces, so let’s put that aside and look at the other parameters.

  • @target () @target specifies the range of objects that the Annotation modifies, that is, the object on which the Annotation is applied: Annotations can be used for packages, types (classes, interfaces, enumerations, Annotation types), type members (methods, constructors, member variables, enumerated values), method parameters, and local variables (such as loop variables, catch parameters). Target is used in the Annotation type declaration to clarify the target it modifies. Function: used to describe the use of annotations range (i.e., described the annotations can be used in what place) values (ElementType) is derived from Java. Lang. The annotation. The ElementType enumerated types of elements: (1).constructor: used to describe the CONSTRUCTOR (2).field: used to describe the FIELD (3).local_variable: used to describe local variables (4).method: used to describe methods (5).package: used to describe packages PARAMETER: used to describe parameters.TYPE: Used to describe classes, interfaces (including annotation types), or enum declarations
  • @retention () @retention defines how long this Annotation is retained: some annotations only appear in source code and are discarded by the compiler; Others are compiled in class files; Annotations compiled in a class file may be ignored by the virtual machine, while others will be read when the class is loaded (note that class execution is not affected, since annotations and classes are used separately). Using this meta-annotation, you can limit the “life cycle” of an Annotation. Role: said need what level in save the annotation information, used to describe the annotation life cycle (i.e., the annotations are described within the scope of what effective) values (RetentionPoicy) from Java. Lang. The annotation. RetentionPolicy enumeration values: (1).source: valid in the SOURCE file (i.e. reserved) (2).class: valid in the CLASS file (i.e. reserved) (3).runtime: valid at RUNTIME (i.e. reserved at RUNTIME)
  • @documented @documented describes other types of annotations that should be treated as a public API for the annotated program members, and therefore can be Documented by tools like Javadoc. Documented is a marked annotation that has no member.
  • @Inherited: The @Inherited meta-annotation is a markup annotation. @Inherited explains that an annotated type is Inherited. If an annotation type with the @Inherited annotation is applied to a class, the annotation will be applied to a subclass of that class. Note: The @Inherited Annotation type is Inherited by a subclass of the annotated class. A class does not inherit annotations from the interface it implements, and a method does not inherit annotations from the method it overloads. When annotation annotation annotated by @Inherited Annotation type is Retention retentionPolicy. RUNTIME, the reflection API enhances this inheritance. When we use java.lang.reflect to query an annotation of @Inherited Annotation type, reflection code inspection will work: Inspect the class and its parent until the specified annotation type is found or reaches the top of the class inheritance structure.
Here is an overview of the meaning and value of each annotation defined on a class. Now we will go into our custom annotation.

Custom annotations

Let’s start by following suit and defining an annotation class

public @interface MyTag {

}Copy the code

The definitions in the notes are also prescriptive:

  • Annotation methods cannot take parameters.

    • Annotation methods return values of type limited to: primitive type, String, Enums, Annotation, or an array of these types.
  • Annotation methods can have default values.

  • Annotations themselves can contain meta-annotations that are used to annotate other annotations.

Let’s give it a try!

Public @interface MyTag {// Declare the return value type, there are no curly braces, you can set the default return value, and then directly";"Ah. String name () default"" ;

    int size () default 0 ;

}Copy the code

Once we have defined our annotations, we can specify where and when to use them.

@Target({ElementType.METHOD,ElementType.FIELD}) @Inherited @Retention(RetentionPolicy.RUNTIME) public @interface MyTag {  String name () default"" ;
    int size () default 0 ;
}Copy the code

Here we define that this annotation can be used on properties and methods, and is an inheritable annotation that can appear at run time. I used retentionPolicy.runtime because we want to mimic the usage of annotations in other annotation frameworks, because we use reflection to get the annotation information in it at RUNTIME. Now let’s see how to use our custom annotations!

public class HomeActivity extends AppCompatActivity {
    @MyTag(name = "BMW",size = 100)
    Car car;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_home); AnnotationCar.instance().inject(this); // When the program runs, it will output the Car property value of the class. Log.e("WANG"."Car is "+car.toString()); }}Copy the code

We define a Car attribute in the Activity, then define our annotations on the Car variable, and assign values to our annotations. Then we initialize our annotation in the onCreate method and print the Car information. Let’s see the result

cn.example.wang.routerdemo E/WANG: Car is Car [name=BMW, size=100]Copy the code

So our custom annotations come into play. Well, the main code is in that initialization.

Public class AnnotationCar {private static AnnotationCar AnnotationCar; public static AnnotationCarinstance(){
        synchronized (AnnotationCar.class){
            if(annotationCar == null){
                annotationCar = new AnnotationCar();
            }
            returnannotationCar; } } public void inject(Object o){ Class<? > aClass = o.getClass(); Field[] declaredFields = aClass.getDeclaredFields();for (Field field:declaredFields) {
            if(field.getName().equals("car") && field.isAnnotationPresent(MyTag.class)) { MyTag annotation = field.getAnnotation(MyTag.class); Class<? >type = field.getType();
                if(Car.class.equals(type)) {
                    try {
                        field.setAccessible(true);
                        field.set(o, new Car(annotation.name(), annotation.size()));
                    } catch (IllegalAccessException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }
}Copy the code

This explains why annotations and reflections enter our knowledge at the same time. Here we first get all the attributes in the class, and then go to find the attribute modified by our annotation MyTag, and then take the value in our annotation, and then assign it to the attribute in our class! So we initialized a property value with an annotation, and that’s the end of it!

conclusion

The example is very simple, will you write a similar ButterKnife effect after watching it? If you have any questions, please leave a message to me, I will answer for you in real time!

Welcome to pay attention to my nuggets welcome to pay attention to my book welcome to pay attention to my CSDN source download