Girlfriend: I want my own annotation, you teach me!
moon: eh? Why do you suddenly want your own annotation?
Girlfriend: none of your business! "Break up"!
moon: No, no, no, no! I teach you!
moon: look at my treasure. You're good at spring. Let me show you Autowired first
@Target({ElementType.CONSTRUCTOR, ElementType.METHOD, ElementType.PARAMETER, ElementType.FIELD, ElementType.ANNOTATION_TYPE}) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface Autowired { /** * Declares whether the annotated dependency is required. * <p>Defaults to {@code true}. */ boolean required() default true; }
moon: when you see "Autowired", you find that the "class name" of this class is called Autowired, so do you know why @ Autowired is posted?
Girlfriend: Oh Oh Oh! I see! The original "class name is the annotation name"!
moon: my girlfriend is smart! Let's take a look again. There is another special thing about it. The class flag is class, and the annotation flag is @ interface.
Girlfriend: Um Good, good, you go on
moon: let's take another look at @ Autowired. There are three annotations on @ Autowired. What are their functions? Let's first look at the first "@ Documented"
/** * Indicates that annotations with a type are to be documented by javadoc * and similar tools by default. This type should be used to annotate the * declarations of types whose annotations affect the use of annotated * elements by their clients. If a type declaration is annotated with * Documented, its annotations become part of the public API * of the annotated elements. * * @author Joshua Bloch * @since 1.5 */ @Documented @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.ANNOTATION_TYPE) public @interface Documented { }
moon: look, we found that the first one is @ Documented. Let's see what its comments are?
moon: through my strong English reading ability, I found that "@ Documented annotation is actually only used to generate documents". api documents can be generated by using javadoc, so this annotation must be "unimportant"
Girlfriend: bah! You obviously rely on translation! study slacker!
moon: Hey, hey, let's see the next one! 「@Retention」! That's enough
/** * Indicates how long annotations with the annotated type are to * be retained. If no Retention annotation is present on * an annotation type declaration, the retention policy defaults to * {@code RetentionPolicy.CLASS}. * * <p>A Retention meta-annotation has effect only if the * meta-annotated type is used directly for annotation. It has no * effect if the meta-annotated type is used as a member type in * another annotation type. * * @author Joshua Bloch * @since 1.5 * @jls 9.6.3.2 @Retention */ @Documented @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.ANNOTATION_TYPE) public @interface Retention { /** * Returns the retention policy. * @return the retention policy */ RetentionPolicy value(); }
moon: again, through my strong English reading ability, what does this annotation mean?
moon: in fact, it tells you how long the "life cycle" of the annotation is, and the definition of this life cycle is "in the RetentionPolicy". Let's see what the RetentionPolicy is?
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 }
Girlfriend: I know this well! "SOURCE means to be applied to the SOURCE code, CLASS means to be applied to the compiled SOURCE code, and RUNTIME means to be applied only to the RUNTIME"! These are the three states of Java!
moon: you have learned to answer my treasure!!!!
Girlfriend: hum! Go on!!
moon: hahaha, OK, let's talk about the last Annotation "@ Target"
@Documented @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.ANNOTATION_TYPE) public @interface Target { /** * Returns an array of the kinds of elements an annotation type * can be applied to. * @return an array of the kinds of elements an annotation type * can be applied to */ ElementType[] value(); }
moon: the function of this annotation is actually very simple, "that is to tell you which scopes the annotation can be pasted in", and what scopes do you know?
Girlfriend: Well There are classes, methods, member variables
moon: hahaha, I don't know!!
Girlfriend: hum!! "Break up"!!!!
moon: No, no, no, no, no, no, no, no, no, no, no, no, no, no, no, no, no, no, no, no, no, no, no, no, no, no, no, no, no, no, no, no, no, no, no! This scope is actually hidden in the "ElementType []" array. Let's go in and have a look!
public enum ElementType { /** Class, interface (including annotation type), or enum declaration */ TYPE, /** Field declaration (includes enum constants) */ FIELD, /** Method declaration */ METHOD, /** Formal parameter declaration */ PARAMETER, /** Constructor declaration */ CONSTRUCTOR, /** Local variable declaration */ LOCAL_VARIABLE, /** Annotation type declaration */ ANNOTATION_TYPE, /** Package declaration */ PACKAGE, /** * Type parameter declaration * * @since 1.8 */ TYPE_PARAMETER, /** * Use of a type * * @since 1.8 */ TYPE_USE }
moon: there are "10 Scopes" in total
Scope | meaning |
---|---|
TYPE | Used to describe a class, interface (including annotation types), or enum declaration |
FIELD | Used to describe a domain |
METHOD | For method |
PARAMETER | Used to describe parameters |
CONSTRUCTOR | Used to describe constructors |
LOCAL_VARIABLE | Used to describe local variables |
ANNOTATION_TYPE | Used to describe annotations |
PACKAGE | Used to describe the package |
TYPE_PARAMETER | Indicates that the annotation can be used in user-defined type parameters |
TYPE_USE | Is a comment on the type |
So when you determine the scope of your annotation, you can paste @ target (SCOPE)!
Girlfriend: Oh, I see. Then I have a question, "what should I do if I want my subclass to inherit this annotation?"?
moon:!!!!!!! That's what I'm going to talk about!! 「@Inherited」 !! It is also one of the four meta annotations of java (the other three are @ target, @ retention, @ documented just mentioned)! Its function is to "let the child class inherit the annotation of the parent class". Do you know how to use it?
Girlfriend: points
moon: let me give you an example! Just practice!
Girlfriend: hum!
moon: let's write an annotation class first
@Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) public @interface MyAnnotation { /** * Say I love you (default true) */ boolean sayILoveYou() default true; }
moon: this annotation is very simple. "It can only work on methods. It is implemented at runtime. There is a syaILoveYou method. The default is true!"
Girlfriend: yue~ come on
moon: haha, define another me. There is a sayLoveYou() method, which pastes our @ MyAnnotation annotation to express my sincerity
public class Me { @MyAnnotation public void sayLoveYou(){ System.out.println("Express my heart"); } }
Girlfriend: yue~
moon: OK, now let's start the test!
public class Main { public static void main(String[] args) { try { //Get the Class object of Me Me me = new Me(); Class clazz = me.getClass(); //Gets the annotation of the Info type on the sayLoveYou method of the object MyAnnotation myAnnotation = clazz.getMethod("sayLoveYou", null).getDeclaredAnnotation(MyAnnotation.class); if (myAnnotation.sayILoveYou()) { System.out.println("I love you!"); } else { System.out.println("i don't love you"); } } catch (Exception e) { e.printStackTrace(); } } }
moon: we first get the Me object, and then get the annotation MyAnnotation. If MyAnnotation If sayiloveyou() is true, it will output "I love you"! If it is false, it will output "I don't love you"!
Girlfriend: you don't love me, "we break up"
moon: cough, test ~ let's run and have a look. The result must be that I love you! Because we default to true
moon: we modify the default value of the annotation, and the result is that I Emm love you (full of desire for survival)
public class Me { @MyAnnotation(sayILoveYou=false) public void sayLoveYou(){ System.out.println("Express my heart"); } }
Girlfriend: hum~
moon: let's try the @ Inherited annotation again, modify MyAnnotation, "add @ Inherited", and add "add ElementType.TYPE and make it work on classes"
@Retention(RetentionPolicy.RUNTIME) @Target({Ele,mentType.METHOD,ElementType.TYPE}) @Inherited public @interface MyAnnotation { /** * Say I love you (default true) */ boolean sayILoveYou() default true; }
Moon: the class me is annotated with @ MyAnnotation on the class
@MyAnnotation public class Me { public void sayLoveYou(){ System.out.println("Express my heart"); } }
moon: then if we have children
public class Child extends Me{ }
Girlfriend: I won't marry you!
moon: hahaha, let's rewrite the Main method
public static void main(String[] args) { try { //Get the Class object of child Child child = new Child(); Class clazz = child.getClass(); //Gets the annotation of the Info type on the sayLoveYou method of the object MyAnnotation myAnnotation = (MyAnnotation) clazz.getAnnotation(MyAnnotation.class); if (myAnnotation.sayILoveYou()) { System.out.println("I love you!"); } else { System.out.println("i don't love you"); } } catch (Exception e) { e.printStackTrace(); } }
moon: "at this time, our child object does not have @ MyAnnotation annotation annotation, but inherits from Me. However, because we pasted @ MyAnnotation annotation annotation and @ Inherited annotation on the Me class, the child also has the annotation function, so the running result must be I love you!"
moon: now you will! Annotation is so simple!
Girlfriend: hum, you're still useful. I don't need you anymore. Let's go
moon: good boss! (finally taught, I survived again)
How many times have you divided your hands? Have you counted them clearly?
Original address: Custom annotation, my girlfriend can!