Understanding advanced Java features--notes

1. What are the notes?

Java Annotation, also known as Java Label, is JDK5.0 introduces a mechanism for annotation, which is a form of metadata that provides data about a program but is not part of the program itself and has no direct impact on the code they annotate.
How do you understand that?
It literally means he's a comment. It's used to annotate, like the labels in the shop, to mark this thing as a cucumber, and to mark this as a watermelon
Let's see how to customize a comment in Java?

2. Definition of Notes

All annotations in Java implement the Annotation interface by default:

package java.lang.annotation;

public interface Annotation {
    boolean equals(Object var1);

    int hashCode();

    String toString();

    Class<? extends Annotation> annotationType();
}

3. Meta-annotations

Meta-annotation: When defining a comment, the annotation class can also use other annotation declarations to annotate the type of annotation, which we call meta-annotation. Generally, when defining a custom annotation, there are two meta-annotations that need to be specified

Two meta-annotations, @Documented and @Inherited, are used to extract documents from Javadoc tools and the latter to allow subclasses to integrate annotations defined in the parent class

@Target
Annotations mark another annotation to limit the types of Java elements that can apply annotations. The target annotation specifies one of the following element types as its value

  • ElementType.TYPE is used for any element of a class (class, interface, annotation, enumeration)
  • ElementType.FIELD applied to fields or attributes
  • ElementType.METHOD applied to method-level annotations
  • ElementType.PARAMETER parameters applied to methods
  • ElementType.CONSTRUCTOR uses for construction methods
  • ElementType.LOCAL_VARIABLE applied to local variables
  • ElementType.ANNOTATION_TYPE Applies to Annotation Types
  • ElementType.PACKAGE applied to package declaration

@ Retention
Annotations specify how tag annotations are stored and are used when they are valid

  • RetentionPolicy.SOURCE tag annotations are kept at the source level only and are ignored by the compiler
  • RetentionPolicy.CLASS tag annotations are reserved by the compiler at compile time and are ignored by a single JVM
  • RetentionPolicy.RUNTIME convenient annotations are reserved by the JVM so runtime environments can use them
    When the compiler is retained, the source-level periods are also available, not just at compile time, as are RUNTIME, which includes SOURCE and CLASS periods

4. Customize a comment

In the meta-annotations, we see that allowing parameters to be passed when using annotations, we can also pass parameters in custom annotations, where the body of the custom annotation contains annotation type elementation annotation type element declarations, looks like a method and can define optional defaults

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.CLASS) //Retention Period of Comments to Compilation Period
@Target({ElementType.TYPE,ElementType.FIELD})//Application and Class Element and Attribute Fields
public @interface BindView {
    String value();//No Default
    int age() default  1; //Has Default Value
}

Use

public class MainActivity extends AppCompatActivity {
//    @BindView("amszlk")
    @BindView(value = "amszlk",age=10)
    private String name;
}

When using annotations, you must pass a value if the type element in the defined annotation has no default value

5. Annotate scenarios

Annotations can be used in three scenarios depending on how they are stored as defined by the @Retention meta-annotation

5.1 SOURCE: Acts on source-level annotations that can be provided for use in scenarios such as IDE grammar checks, APT s, etc.

5.1.1, IDE grammar check

In Android development, in support-annotation and Androidx. The @IntDef annotation, defined as follows, is provided in annotations

@Retention(SOURCE)//Source-level annotations
@Target({ANNOTATION_TYPE})
public @interface IntDef {
    /** Defines the allowed constants for this element */
    int[] value() default {};

    /** Defines whether the constants can be used as a flag, or just as an enum (the default) */
    boolean flag() default false;

    /**
     * Whether any other values are allowed. Normally this is
     * not the case, but this allows you to specify a set of
     * expected constants, which helps code completion in the IDE
     * and documentation generation and so on, but without
     * flagging compilation warnings if other values are specified.
     */
    boolean open() default false;
}

The essence of enumeration in Java is a static member variable of a special case. All enumerated classes at run time are loaded into memory as a single case, which takes up 5 to 10 times more memory than a constant. The significance of this annotation is to replace enumeration and to implement method access restriction
Example:
We define a method, test, that receives the parameter coder and needs to select one of the two in Java and JavaScript

public enum Coder {
    JAVA,JAVASCRIPT
}
public void test(Coder coder){
    
}

We are not using enumerations now for memory optimization

public class Test {
    public static  final  int JAVA=1;
    public static final int JAVASCRIPT=2;
    
   public void test(int coder){
       
   }
}

At this point, however, the test method is called, and because it is using test, it cannot be type-qualified. It can pass numbers other than 1 and 2, which is why we can add custom annotations with @IntDef

    @IntDef(value={JAVA,JAVASCRIPT})//Limited to JAVA and JAVASCRIPT
    @Target(ElementType.PARAMETER)//Acting on parameters
    @Retention(RetentionPolicy.SOURCE)//Source Level Comments
    public @interface Coder {
    }
   public void test(@Coder int coder){

   }

This way, parameters passed when called will fail if they are not JAVA and JAVASCRIPT

5.1.2APT Annotation Processor

APT: Annotation Processor Tools Annotation Processor Processor Processor, which is used to process annotations and write Java source files. It needs to be compiled by javac and translated into a byte code file Class file that the virtual machine can load and parse. Annotation Processor is a tool that comes with javac to scan and process annotation information at compile time. You can register your own annotation processor for some annotations, which are raised by javac and passed annotation information to the annotation processor for processing
Annotation processors are the most widely used scenarios for annotations. There are annotation processors in Glide, ARouter, ButterKnifer, Tinker, EventBus and other frameworks. The definition of annotation in these frameworks is not Source level, but Class level, because Class level contains Source level.

5.2CLASS

Annotations defined as CLASS are retained in the class file but are ignored by the virtual machine, that is, they cannot be reflected at runtime to get annotations. The scenario in which this annotation fits perfectly is a bycode operation, such as in a hot-fix Roubust
Byte Code Operation: Direct modification of the byte code class file for the purpose of modifying code execution logic
Let's take a chestnut: login interception, there are many places in our program that need to be judged whether to login or not, to judge whether to login or not, it is through validation and login without login. If you use the common encoding method, you add if else to many methods, but with the CLASS period notes, we can use AOP. Divide all the function points in the program into two facets: those requiring login and those not requiring login. Use notes to distinguish facets

    @Target(ElementType.METHOD)
    @Retention(RetentionPolicy.CLASS)
    public @interface Login{
        
    }
    @Login
    public void jumpAActivity(){
        
    }
    public void jumpBActivity(){
        
    }

In the above code, we can get a method annotated as Login in the byte code compiled by the class, then manipulate the byte code, modify the contents of the class, and add if else

//Class file
@Login
public void jumpAActivity(){
	if(this.isLogin)  {
		this.startActivity(new Intent(this,LogingActivity.class))
	} else {
		this.startActivity(new Intent(this,AActivity.class))
	}     
 } 

5.3 RUNTIME

Keeping annotations up to runtime means we can combine reflection technology to get all the information in the annotations during runtime
Reflection and Dynamic Proxy Points I View

6. Summary

This article has learned notes from the definition of notes, the use and use of scenarios, and will combine other techniques to learn later. Technology can't be learned just for learning. We need to put them to the ground and put them into practice! Let's come on together! Hope the big guys keep up!

Keywords: Java Android

Added by lepad on Mon, 31 Jan 2022 22:05:24 +0200