Tags: Java foundation


What are annotations?

Comments: the Annotation…

Annotations are simply special tags in code that can be read at compile time, class load time, run time, and perform the appropriate processing.

Why do we need annotations?

Traditionally, configuration files (XML files) have been used to tell classes how to run.

With annotations, we can use annotations to tell a class how to behave, right

For example, when we were writing servlets, we needed to configure specific information in the web.xml file

After using annotations, we can add annotations directly to the Servlet source code… The Servlet is configured on Tomcat. That is, annotations can inject information into classes and methods.

Obviously, this is very straightforward, and the Servlet specification favors this configuration.

The basic Annotation

There are five basic annotations in the java.lang package, of which three are very common.

@Overried

Rewrite the annotation

If we override the parent method using the IDE, we can see it. So what does it do?

@overried is telling the compiler to check that the method is implementing a parent class… Can help us avoid some silly mistakes…

For example, if we mistyped euqals() when we implemented equals(), the compiler would realize that the method didn’t implement the parent class, which conflicts with the @overried annotation, and would give an error.


@Deprecated

Outdated annotations

This annotation is also very common. When Java is designing, it may decide that some method is not well designed and cannot be discarded in order to be compatible with previous programs, so it is made obsolete.

ToLocalString () in the Date object is set to obsolete

    @Deprecated
    public String toLocaleString(a) {
        DateFormat formatter = DateFormat.getDateTimeInstance();
        return formatter.format(this);
    }
Copy the code

When we call it in a program, a bar appears on the IDE indicating that the method is obsolete.


@SuppressWarnings

Suppress compiler warning annotations

This annotation is not very common when we write programs, and we can use it to get the compiler not to warn us

When we use collections, if generics are not specified, a security check is prompted

If we add the @SuppressWarnings annotation to the class, the compiler will not warn us

@SafeVarargs

Java 7 heap contamination warning

What is heap pollution? Heap contamination can easily occur when assigning a non-generic set to a generic set….

This annotation is also used to suppress compiler warnings… Use of the place is not much, I will not elaborate on…… Come back and fill in the hole when you need it.

@FunctionalInterface

The @functionalInterface command is used to specify that the interface is functional

Use this annotation to specify that the interface is a functional interface.


Custom annotations

These are the five annotations in the java.lang package. You can write your own annotations to inject information into a method or class.

Mark the Annotation

An annotation without any member variables is called a tag annotation, and @overried is a tag annotation


// It's kind of like defining an interface, except with an @
public @interface MyAnnotation {
    
}

Copy the code

Metadata Annotation

We can customize annotations with member variables, and defining annotations with member variables is called metadata Annotation

Member variables are defined in annotations using the same syntax as declaration methods….


public @interface MyAnnotation {

    // Two member variables are defined
    String username(a);
    int age(a);
}

Copy the code

Note: Member variables defined on annotations can only be Strings, arrays, classes, enumerated classes, annotations

Some people may wonder why an annotation member variable is defined on an annotation. Sounds complicated….

As mentioned above, annotations are used to inject information into classes and methods. So we often use XML files to tell programs how to run. XML is often nested


<book>
	<The author>zhongfucheng</The author>
	<The price>22222</The price>

</book>

Copy the code

So, when we use annotations, we may also need to have nesting, so we allow the annotation to define member variables as annotations.

Use custom annotations

Now that we have defined an annotation, let’s use it

Routine use of

Here I have an add method that needs username and age parameters. Let’s annotate the method to own these two variables!


	// What attribute does an annotation have that should be given the corresponding value when it is decorated
    @MyAnnotation(username = "zhongfucheng", age = 20)
    public void add(String username, int age) {}Copy the code

The default value

Of course, we can give the default value when the annotation declares the attribute. So you don’t have to specify it when you’re decorating.


public @interface MyAnnotation {

    // Two member variables are defined
    String username(a) default "zicheng";
    int age(a) default 23;
}

Copy the code
  • There is no need to give specific values when decorating

    @MyAnnotation(a)public void add(String username, int age) {}Copy the code

The annotation attribute is value

In a special case, if there is only one attribute on the annotation and the name of the attribute is value, we can simply assign the value to it without writing value


public @interface MyAnnotation2 {

    String value(a);
}

Copy the code
  • With annotations, you can assign a value without specifying it

    @MyAnnotation2 ("zhongfucheng")
    public void find(String id) {}Copy the code

Inject basic information about custom annotations into methods

We have used annotations above, but so far there is no correlation between the information on annotations and the information on methods.

When we use Servlet annotations, only the annotations are called and the annotations are in effect. This is the Web container that implements the interior. The custom annotations that we write ourselves need to be handled by ourselves.

Now the question is, how do we inject the information from annotations into the method?? We use reflection technology

The steps can be divided into three parts:

  • A method that reflects the class
  • Use methods to get specific information on annotations
  • Inject the information from the annotation into the method

        // The method that reflects the class
        Class aClass = Demo2.class;
        Method method = aClass.getMethod("add", String.class, int.class);

        // Use this method to get the specific information on the annotation
        MyAnnotation annotation = method.getAnnotation(MyAnnotation.class);
        String username = annotation.username();
        int age = annotation.age();

        // Inject the information from the annotation into the method
        Object o = aClass.newInstance();
        method.invoke(o, username, age);
Copy the code

When we execute, we find exceptions…

At this point, we need to add a line ** to our custom annotations (we’ll see why)**


	@Retention(RetentionPolicy.RUNTIME)
Copy the code

When executed again, we will see that we can inject information into the method through annotations.


The JDK yuan the Annotation

We’ve already covered a few basic annotations under the java.lang package. In addition to annotations under the java.lang package, there are several commonly used meta-annotations under java.lang. Annotation.

Several meta-annotations under the Annotation package are used to modify other annotation definitions.


@Retention

Above, we finally added the @retention annotation…. before injecting the annotation information into the method Otherwise an error will be reported.. What is it used for?

@Retention can only be used to modify other annotations, which specifies how long the modified Annotation will be retained.

@Retention contains a value variable of type RetentionPolicy, so you must assign a value to the value member variable when using it

The value variable has only three values:


public enum RetentionPolicy {
    /** * Annotations are to be discarded by the compiler. */
    SOURCE,

    /** * Annotations are to be recorded in the class file by the compiler * but need not be retained by the VM at run time.  This is the default * behavior. */
    CLASS,

    /**
     * Annotations are to be recorded in the class file by the compiler and
     * retained by the VM at run time, so they may be read reflectively.
     *
     * @see java.lang.reflect.AnnotatedElement
     */
    RUNTIME
}

Copy the code

Java files have three phases: compile,class, and run. @retention defaults to class

Previously we used reflection to get the information in the annotation because @Retention defaults to class and reflection gets the information at runtime. So I don’t get the Annotation information. Therefore, it is necessary to change its RetentionPolicy value on the custom annotation


@Target

@target can also only be used to modify another Annotation, which specifies which program unit the modified Annotation should be used to modify

@target is a single value member variable that has the following values:


public enum ElementType {
    /** Class, interface (including annotation type), or enum declaration */
    TYPE,

    /** Field declaration (includes enum constants) */
    FIELD,

    /** Method declaration */
    METHOD,

    /** Parameter declaration */
    PARAMETER,

    /** Constructor declaration */
    CONSTRUCTOR,

    /** Local variable declaration */
    LOCAL_VARIABLE,

    /** Annotation type declaration */
    ANNOTATION_TYPE,

    /** Package declaration */
    PACKAGE
}

Copy the code

If @target specifies elementType. ANNOTATION_TYPE, then the decorated Annotation can only decorate Annotaion


@Documented

Documented Specifies that the Annotation class modified by this Annotation will be extracted into a document by the Javadoc tool.

This meta-annotation is used sparingly….


@Inherited

Inherited is also used to modify other annotations. Annotations that are modified will be Inherited…

Example:

  1. @xxx is my custom annotation. I now use…. on the Base class using the @xxx annotation
  2. Use @Inherited to decorate @xxx annotations
  3. When a class inherits from the Base class, the implementation class automatically has the @xxx annotation

Inject an object into a method

Previously we have been able to use annotations to inject basic information into the method. Now we will use an object to inject the method…..

As mentioned above, annotations can only define member variables such as strings, enumerated classes, and doubles. How do you inject objects into methods?

Simulation scenario:

  • The Person class, which defines the username and age properties, has getter and setter methods for uerName and age

public class Person {
    
    private String username;
    private int age;

    public String getUsername(a) {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public int getAge(a) {
        return age;
    }

    public void setAge(int age) {
        this.age = age; }}Copy the code
  • PersonDao class. The PersonDao class defines the Person object and has setter and getter methods for Person

public class PersonDao {
    
    private Person person;

    public Person getPerson(a) {
        return person;
    }

    public void setPerson(Person person) {
        this.person = person; }}Copy the code
  • Now all I have to do is inject the Person object into the setPerson() method using an annotation, setting the Person attribute of the PersonDao class

public class PersonDao {

    private Person person;

    public Person getPerson(a) {
        return person;
    }


	Inject a Person object whose username is zhongfucheng and age is 20 into the setPerson method
    @InjectPerson(username = "zhongfucheng",age = 20)
    public void setPerson(Person person) {
        
        this.person = person; }}Copy the code

Steps:

① : to define a custom annotation, attribute is consistent with the JavaBean class


// The injection tool uses reflection to get the annotation information, so the reserved domain must use RunTime
@Retention(RetentionPolicy.RUNTIME)
public @interface InjectPerson {

    String username(a);
    int age(a);
}

Copy the code

② : Write injection tools


        //1. Use introspection to get the attributes you want to inject
        PropertyDescriptor descriptor = new PropertyDescriptor("person", PersonDao.class);

        //2. Get the concrete object you want to inject properties into
        Person person = (Person) descriptor.getPropertyType().newInstance();

        [setPerson()]
        Method method = descriptor.getWriteMethod();

        //4. Get comments on writing methods
        Annotation annotation = method.getAnnotation(InjectPerson.class);

        //5. Get the information on the annotation.
        Method[] methods = annotation.getClass().getMethods();

        //6. Populate the person object with the information from the annotation

        for (Method m : methods) {

            // Get the name of the attribute on the annotation.
            String name = m.getName();

            SetAge (),setName()
            try {

                //6.1 It is assumed that there is a corresponding write method, and the write method is obtained
                PropertyDescriptor descriptor1 = new PropertyDescriptor(name, Person.class);
                Method method1 = descriptor1.getWriteMethod();//setAge(), setName()

                // Get the value in the annotation
                Object o = m.invoke(annotation, null);

                // Call the setter method of the Person object to set the value on the annotation
                method1.invoke(person, o);

            } catch (Exception e) {

                // the 6.2 Person object has no corresponding method and jumps to a catch. We're just going to let it go through the annotations
                continue; }}// When the program is done iterating, the Person object is already populated with data

        // assign the person object to the PersonDao
        PersonDao personDao = new PersonDao();
        method.invoke(personDao, person);

        System.out.println(personDao.getPerson().getUsername());
        System.out.println(personDao.getPerson().getAge());


Copy the code

③ : Summarize the steps

We actually inject objects into methods like this:

  • Gets the property you want to inject into the class
  • Gets the object of this property
  • Get the corresponding write method of the property
  • Get annotations by writing them
  • Get annotation details
  • Inject annotated information into the object
  • The property write method is called to inject an object filled with data into the method

Inject an object into a member variable

Now that we’ve seen how to inject objects into methods, injecting them into member variables is pretty straightforward.

Steps:

① : Use annotations on member variables


public class PersonDao {

    @InjectPerson(username = "zhongfucheng",age = 20) private Person person;

    public Person getPerson(a) {
        return person;
    }
    
    public void setPerson(Person person) {

        this.person = person; }}Copy the code

② : Write injection tools


        //1. Get the attributes you want to inject
        Field field = PersonDao.class.getDeclaredField("person");

        //2. Get the concrete object of the attribute
        Person person = (Person) field.getType().newInstance();

        //3. Get the annotation on the property
        Annotation annotation = field.getAnnotation(InjectPerson.class);

        //4. Get the attribute of the annotation.
        Method[] methods = annotation.getClass().getMethods();

        //5. Populate the injected properties into the Person object
        for (Method method : methods) {

            //5.1 Get the name of the annotation property
            String name = method.getName();

            // See if there is a corresponding write method on the Person object
            try {

                / / if you have
                PropertyDescriptor descriptor = new PropertyDescriptor(name, Person.class);

                // Get the write method on the Person object
                Method method1 = descriptor.getWriteMethod();

                // Get the value on the annotation
                Object o = method.invoke(annotation, null);

                // Populate the Person object
                method1.invoke(person, o);
            } catch (IntrospectionException e) {

                // If there is no desired attribute, continue the loop
                continue; }}// After the loop, the person is already populated with data


        Set the Person object to the PersonDao
        PersonDao personDao = new PersonDao();
        field.setAccessible(true);
        field.set(personDao, person);

        System.out.println(personDao.getPerson().getUsername());
Copy the code

conclusion

① : the steps of injecting objects: get the object attributes you want to inject, get the information of annotations through attributes, inject the information of annotations into the object through the writing method of attributes, and finally assign the object to the class.

② : Annotations are actually two functions:

  • Let the compiler examine the code
  • Inject data into methods, member variables, and classes

If you find this article helpful, give the author a little encouragement