A picture is introduced at the beginning of the article.



This picture is taken from Lao Luo’s blog. In order to avoid unnecessary trouble, FIRST of all, I have a personal respect for Lao Luo. As for why this image is there, it’s for this blog post, which I’ll explain next. Ok, ready to start today’s blog post.

Annotation is a very important topic in Java, but it is often a bit difficult for beginners to understand.

In my opinion, one of the main characteristics of bad technical documentation is the use of technical terms to introduce technical terms.

Such as:

Java annotations are used to provide metadata to Java code. As metadata, annotations don’t directly affect your code execution, but there are some types of annotations that can actually be used for this purpose. Java annotations were added to Java starting with Java5.

These are Java annotations on most websites, and the explanation is true, but to be honest, when I first learned it, my mind went blank. What the hell is that? I heard it like I didn’t. Because the concept is too abstract, so beginners are really more difficult to understand, and then with their own development process constantly strengthen the practice, will slowly form a correct understanding of it.

As I write this, I am thinking. How can YOU make yourself or your readers more intuitive about the concept of annotations? Do you want to translate instructions on official documents? I immediately rejected the answer.

Later, I thought of something ———— ink, ink can be volatile, can be different colors, used to explain the annotations just right.

But as I continued to think, I came up with a better substitute for ink: a seal. The seal can be stained with different inks or prints, the words or patterns of the seal can be customized, and it can be poked on any surface you wish.

However, as I continued my thinking, I came up with a better alternative to a seal: a tag. A label is a convenience paper, and the contents of the label can be defined freely. Common ones are commodity price tags on shelves, book code labels in libraries, names and categories of chemical materials in laboratories, and so on.

And, to put it abstractly, a label is not necessarily a piece of paper, it can be an attribute evaluation of people and things. In other words, labels have an interpretation of abstract things.

So, with that in mind, I completed my knowledge upgrade, and I decided to annotate with labels.

Annotations as labels

Back to the beginning of the blog, there was a habit of building a building in the comments of a news client, so “Jobs redefined the mobile phone, Luo Yonghao redefined the stupid X” often appeared in the comments floor very neatly, and the majority of netizens were very happy with this behavior for a long time. This is the equivalent of labeling.

In the eyes of some netizens, Luo yonghao has become a synonym for silly X.

The broad masses of netizens to Mr Luo to stick a label called “silly x”, they don’t really know Mr Luo, don’t know him as a teacher, hit the feat of refrigerator, blogging, but because of “dumb” tag, which would help them directly to Mr Luo this man quickly make evaluation, and then based on this, Mr Luo can become in dinner conversation, That’s the power of labels.

On the other side of the network, Luo relies on his personality charm to naturally gain a large number of loyal fans, they stick to luo is another label.

Lao Luo is still Lao Luo, but because people attach different labels to it, so it causes different views on him. People who don’t like him criticize and mock on the network all day long, while those who admire him will be willing to earn money to buy the release tickets of Smartisan mobile phone.

I don’t want to evaluate either behavior, but let me give you another example.

“Science says” is very popular on the Internet debate in recent years, the debater Ming Chen was another debater wei-wei ma attack say – “stand in the center of the universe called love”, and then a big label – – “the man with the chicken soup”, since then, the audience to see Ming Chen, the first thing in my mind is “chicken soup” three characters, In fact, Chen Ming is very good as a teacher, decent style, decent manners, but in the network, because of the environment of entertainment first, people are more willing to take the attitude of entertainment to recognize everything, so “chicken soup man” as Chen Ming himself said has become an inseparable label.

We can generalize abstractly, label is the evaluation and explanation of certain Angle of the behavior of things.

Here, finally can lead to the main notes of this article.

A beginner can think of annotations this way: think of code as living. A annotation is a label attached to some living individual in the code. In a nutshell, a annotation is like a label.

Before you start learning the syntax of any annotations, you can think of a annotation as a label. This will help you quickly understand what it does in general. If the beginner has a blank in the learning process, please don’t panic, say to yourself:

Annotations, labels. Annotations, labels.

Annotation syntax

Because the common development is rare, I believe that many people will think that the status of annotations is not high. Annotations are of a type, just like classs and interfaces. It was introduced in Java SE 5.0.

Definition of annotations

Annotations are defined by the @interface keyword.

public @interface TestAnnotation {
}Copy the code

It looks like an interface, but with an @ sign in front of it. The above code creates an annotation named TestAnnotaion.

You can simply create a label named TestAnnotation.

Application of annotations

The above created an annotation, so how to use the annotation is what.

@TestAnnotation
public class Test {
}Copy the code

To annotate the class with TestAnnotation, create a class Test and add @testannotation to the class definition.

This can be interpreted as simply adding the notation tag to the Test class.

However, for annotations to work properly, a new concept needs to be introduced: meta-annotations.

Yuan notes

What does a meta-annotation mean?

A meta-comment is a comment that can be added to a comment, or a meta-comment is a basic comment that can be applied to other comments.

If it’s hard to understand, you can understand it like this. A meta-annotation is also a tag, but it is a special tag whose function and purpose is to explain other common tags.

Meta labels include @Retention, @documented, @target, @Inherited, and @REPEATable.

@Retention

Retention Retention means Retention period. When @Retention is applied to a annotation, it explains the annotation’s lifetime.

The -retentionPolicy. SOURCE annotation is only retained at the SOURCE stage and is discarded and ignored when the compiler compiles. The -retentionPolicy.class annotation is only reserved until compilation, and it is not loaded into the JVM. – RetentionPolicy.RUNTIME annotations can be retained until the application is run. They are loaded into the JVM, so they can be retrieved while the application is running.

We can deepen our understanding by saying that @Retention specifies when a label is interpreted, it specifies when the label is posted. @Retention is the equivalent of stamping a label with a time stamp that specifies the period in which the label was posted.

@Retention(RetentionPolicy.RUNTIME)
public @interface TestAnnotation {
}Copy the code

In the code above, we specified that the TestAnnotation notation can be accessed during the run cycle of the program, so its life cycle is very long.

@Documented

As the name implies, this meta-annotation must be related to the document. It provides the ability to include elements from annotations into Javadoc.

@Target

Target means Target, and @target specifies where the annotation should be used.

As you can see, when an annotation is annotated by @target, the annotation is restricted to the context in which it is used.

By analogy, tags can be posted anywhere you want, but thanks to @target, they can only be posted to methods, classes, method parameters, and so on. At sign Target has the following values

  • Elementtype. ANNOTATION_TYPE Annotates an annotation
  • Elementtype. CONSTRUCTOR can be annotated to a CONSTRUCTOR
  • Elementtype. FIELD can be used to annotate attributes
  • Elementtype. LOCAL_VARIABLE can be used to annotate local variables
  • ElementType.METHOD can annotate methods
  • Elementtype. PACKAGE can annotate a PACKAGE
  • Elementtype. PARAMETER can be used to annotate parameters within a method
  • Elementtype. TYPE can annotate a TYPE, such as a class, interface, or enumeration

@Inherited

Inherited means Inherited, but it does not mean that the annotations themselves can be Inherited. It means that if a superclass is annotated by @Inherited annotations, then if its subclass is not applied by any annotations, it inherits the superclass’s annotations. It’s more abstract. Code to explain.

@Inherited
@Retention(RetentionPolicy.RUNTIME)
@interface Test {}


@Test
public class A {}


public class B extends A {}
Copy the code

The Test annotation is annotated by @inherited, and when class A is annotated by Test, class B inherits FROM A, and class B has the Test annotation.

It can be interpreted as follows:

Lao Tzu is very rich, so people give him a label called rich.

When Lao Tze’s son grows up, as long as he does not break off the father-son relationship with Lao Tze, although others do not label him, he is naturally rich.

My grandson grew up, of course, also rich.

These are the so-called rich generation, rich second generation, rich third generation. Although the name is different, like a lot of labels, but in fact, the essence of the matter is that they have a common label, that is, laozi’s rich label.

@Repeatable

Repeatable means Repeatable. Repeatable @repeatable was added to Java 1.8, so it’s a new feature.

What annotations are used more than once? Usually the value of an annotation can be multiple at the same time.

Take, for example, a person who is a programmer, a product manager, and a painter.


@interface Persons {
    Person[]  value();
}


@Repeatable(Persons.class)
@interface Person{
    String role default "";
}


@Person(role="artist")
@Person(role="coder")
@Person(role="PM")
public class SuperMan{

}
Copy the code

Notice the code above, @REPEATable annotates Person. The class in parentheses after @REPEATable is equivalent to a container annotation.

What are container annotations? It’s a place to store other notes. It is a note in itself.

Let’s look again at the relevant container annotations in the code.

@interface Persons {
    Person[]  value();
}Copy the code

As specified, it must have a value property in it. The property type is an array of annotations annotated by @REPEATable. Note that it is an array.

If it’s hard to understand, you can understand it this way. Persons is a generic tag filled with Person tags of the same type but with different content. To label Persons as SuperMan is to label him as programmer, product manager and painter.

We may be interested in the parenthesis of @person (role= “PM”), which essentially assigns the role attribute of the annotation to PM.

Attributes of annotations

Attributes of annotations are also called member variables. Annotations have only member variables and no methods. An annotation’s member variable is declared in the annotation definition as a method of invisible parameters, whose method name defines the name of the member variable, and whose return value defines the type of the member variable.

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface TestAnnotation {

    int id();

    String msg();

}Copy the code

The code above defines the TestAnnotation annotation that has the ID and MSG attributes. When used, we should assign values to them.

This is done by enclosing the annotation in parentheses with the form value= “”, separated from multiple attributes by a comma.

@TestAnnotation(id=3,msg="hello annotation")
public class Test {

}Copy the code

Note that the type of an attribute defined in an annotation must be the eight basic data types plus classes, interfaces, annotations, and their arrays.

Attributes in annotations can have default values, which need to be specified with the default key value. Such as:

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface TestAnnotation {

    public int id(a)default- 1;public String msg(a)default "Hi";

}
Copy the code

The default value of the ID attribute in TestAnnotation is -1 and the default value of the MSG attribute is Hi. It can be applied like this.

@TestAnnotation(a)public class Test {}Copy the code

There is no need to assign the notation inside the parentheses following the @testannotation notation because there are default values. This step can be omitted.

And there’s another situation. If an annotation contains only one attribute named value, you can apply the annotation directly to the attribute value in parentheses.

public @interface Check {
    String value();
}Copy the code

In the code above, the Check annotation only has the value attribute. So you can apply it this way.

@Check("hi")
int a;Copy the code

This has the same effect as the following

@Check(value="hi")
int a;Copy the code

Finally, note that an annotation has no attributes. Such as

public @interface Perform {}
Copy the code

So when applying this annotation, the parentheses can be omitted.

@Perform
public void testMethod() {}Copy the code

Java preconfigured annotations

With this knowledge, we can now define our own annotations. The Java language itself already provides several annotations.

@Deprecated

This element is used to mark obsolete elements, which you might encounter in your daily development. When the compiler encounters this annotation at compile time, it will issue a reminder warning that the developer is calling an outdated element such as an outdated method, an outdated class, or an outdated member variable.

public class Hero {

    @Deprecated
    public void say(){
        System.out.println("Noting has to say!");
    }


    public void speak(){
        System.out.println("I have a dream!"); }}Copy the code

Defines a Hero class that has two methods say() and speak(), where say() is annotated by @deprecated. We then call them separately from the IDE.

As you can see, the say() method is crossed with a line, which is essentially a reminder of the compiler’s recognition.

@Override

This should be familiar, reminding subclasses to Override the @override method in their parent class

@SuppressWarnings

Prevent warning meaning. As mentioned earlier, the compiler will warn you when calling a method annotated by @deprecated, and sometimes developers will ignore this warning. They can do this by calling @SuppressWarnings from where they were called.

@SuppressWarnings("deprecation")
public void test1(){
    Hero hero = new Hero();
    hero.say();
    hero.speak();
}Copy the code

@SafeVarargs

Parameter safety type annotations. Its purpose is to warn developers not to do anything unsafe with arguments, and its existence prevents compilers from generating such warnings. It was added in version 1.7 of Java.

@SafeVarargs // Not actually safe!
    static void m(List<String>... stringLists) {
    Object[] array = stringLists;
    List<Integer> tmpList = Arrays.asList(42);
    array[0] = tmpList; // Semantically invalid, but compiles without warnings
    String s = stringLists[0].get(0); // Oh no, ClassCastException at runtime!
}Copy the code

In the above code, no errors are reported at compile time, but ClassCastException is thrown at runtime, so it tells the developer to take care of it, but the developer is still screwing up.

Future versions will authorize the compiler to issue error warnings about unsafe operations, according to official Java documentation.

@FunctionalInterface

Functional interface annotations, a new feature introduced in Java 1.8. Functional programming is hot, so Java 8 added this feature just in time.

A Functional Interface is a plain Interface with a method.

Such as

@FunctionalInterface
public interface Runnable {
    /**
     * When an object implementing interface <code>Runnable</code> is used
     * to create a thread, starting the thread causes the object's
     * <code>run</code> method to be called in that separately executing
     * thread.
     * <p>
     * The general contract of the method <code>run</code> is that it may
     * take any action whatsoever.
     *
     * @see     java.lang.Thread#run()
     */
    public abstract void run(a); }Copy the code

The Runnable we use in threaded development is a typical FunctionalInterface annotated by @functionalinterface.

One might wonder why functional interface tags are useful, because functional interfaces can be easily converted to Lambda expressions. This is another topic, if you are interested, please search for related knowledge points to learn.

Annotation extraction

The previous section of this post covered the basic syntax of annotations, and now it’s time to examine what we’ve learned.

I’m comparing annotations with tags, and the previous section is about how to write annotations and where to post them, and now what we’re going to do is review the tags. The figurative metaphor is that you tear off these annotations at the right time and review the information on them.

The only way to properly review annotations is through reflection.

Annotations and reflections.

Annotations are obtained by reflection. You can first determine whether an annotation is applied to a Class object using the isAnnotationPresent() method

public boolean isAnnotationPresent(Class<? extends Annotation> annotationClass) {}
Copy the code

The Annotation object is then obtained using the getAnnotation() method.

 public <A extends Annotation> A getAnnotation(Class<A> annotationClass) {}
Copy the code

Or getAnnotations().


public Annotation[] getAnnotations() {}Copy the code

The former method returns the annotations of the specified type, and the latter method returns all annotations annotated to the element.

If the annotations you get are not null, then you can call their property methods. Such as

@TestAnnotation(a)public class Test {

    public static void main(String[] args) {

        boolean hasAnnotation = Test.class.isAnnotationPresent(TestAnnotation.class);

        if ( hasAnnotation ) {
            TestAnnotation testAnnotation = Test.class.getAnnotation(TestAnnotation.class);

            System.out.println("id:"+testAnnotation.id());
            System.out.println("msg:"+testAnnotation.msg()); }}}Copy the code

The result of the program is:

id:-1
msg:
Copy the code

This is the default value for ID and MSG in TestAnnotation.

In the example above, we just check out the annotations on the class, but the annotations on the properties and methods are still ok. Again, it’s a reflex.

@TestAnnotation(msg="hello")
public class Test {

    @Check(value="hi")
    int a;


    @Perform
    public void testMethod() {}@SuppressWarnings("deprecation")
    public void test1(){
        Hero hero = new Hero();
        hero.say();
        hero.speak();
    }


    public static void main(String[] args) {

        boolean hasAnnotation = Test.class.isAnnotationPresent(TestAnnotation.class);

        if ( hasAnnotation ) {
            TestAnnotation testAnnotation = Test.class.getAnnotation(TestAnnotation.class);
            // Get class annotations
            System.out.println("id:"+testAnnotation.id());
            System.out.println("msg:"+testAnnotation.msg());
        }


        try {
            Field a = Test.class.getDeclaredField("a");
            a.setAccessible(true);
            // Get an annotation on a member variable
            Check check = a.getAnnotation(Check.class);

            if( check ! =null ) {
                System.out.println("check value:"+check.value());
            }

            Method testMethod = Test.class.getDeclaredMethod("testMethod");

            if( testMethod ! =null ) {
                // Get the annotation in the method
                Annotation[] ans = testMethod.getAnnotations();
                for( int i = 0; i < ans.length; i++) { System.out.println("method testMethod annotation:"+ans[i].annotationType().getSimpleName()); }}}catch (NoSuchFieldException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
            System.out.println(e.getMessage());
        } catch (SecurityException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
            System.out.println(e.getMessage());
        } catch (NoSuchMethodException e) {
            // TODO Auto-generated catch blocke.printStackTrace(); System.out.println(e.getMessage()); }}}Copy the code

Their results are as follows:

id:-1
msg:hello
check value:hi
method testMethod annotation:Perform
Copy the code

Note that @Retention(retentionPolicy.runtime) is required if an annotation is to be successfully extracted at RUNTIME.

Usage scenarios for annotations

I’m sure all of you are familiar with annotations at this point in this post, but many of you are asking, what are annotations really for?

Yeah, what’s the point of a note?

Let’s take a look at the official Java documentation.

At the beginning of this article, I used tags as an analogy for annotations. But the label metaphor is a means to me, not an end. So that you can learn annotations for the first time without being overwhelmed by new abstract concepts. Now that we know about annotations, we might as well take a closer look at the most official documentation.

Annotations are a set of metadata that provides data to interpret program code, but annotations are not part of the interpreted code itself. Annotations have no direct effect on how the code works.

Annotations have many uses, mainly as follows: – Provide information to the compiler: the compiler can use annotations to detect errors and warnings – compile-time processing: software tools can use annotations to generate code, Html documents, and other processing. – Runtime processing: Some annotations can accept code extraction while the program is running

It is important to note that annotations are not part of the code itself.

If it’s hard to understand, look at it this way. Luo Yonghao is still Luo Yonghao, will not change because some people for his “stupid X” evaluation, the label is just some people for other things, but the label does not change the thing itself, the label is only a means of specific groups of people. So again, annotations don’t change the code itself; annotations are just tools of some tool.

Back to the official documentation, annotations are mainly for compilers and other SoftWare tools.

When the developer modiifies the class, method, Field and other members with annotations, these annotations will not take effect by themselves. The developer must provide the corresponding code to extract and process Annotation information. These codes that extract and process annotations are called APT (Annotation Processing Tool).

Now, we can answer for ourselves, what is the use of annotations? For who? For compiler or APT.

Annotation Application Example

Annotations are used in a lot of places, but as an Android developer, I’ve been exposed to the following examples:

JUnit

JUnit is a testing framework, typically used as follows:

public class ExampleUnitTest {
    @Test
    public void addition_isCorrect(a)throws Exception {
        assertEquals(4.2 + 2); }}Copy the code

@test marks the method to be tested with addition_isCorrect().

ButterKnife

ButterKnife is one of the most well-known IOC frameworks in Android development, which reduces a lot of repetitive code.

public class MainActivity extends AppCompatActivity {

    @BindView(R.id.tv_test)
    TextView mTv;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        ButterKnife.bind(this); }}Copy the code

Dagger2

It is also a well-known dependency injection framework.

Retrofit

Awesome Http network access framework

public interface GitHubService {
  @GET("users/{user}/repos")
  Call<List<Repo>> listRepos(@Path("user") String user);
}

Retrofit retrofit = new Retrofit.Builder()
    .baseUrl("https://api.github.com/")
    .build();

GitHubService service = retrofit.create(GitHubService.class);
Copy the code

There are, of course, many other places where annotations can be used, not listed here.

conclusion

  1. If annotations are difficult to understand, you can think of them as tags that explain things and annotations that explain code.
  2. The basic syntax for annotations is created like an interface, but with an extra @ sign.
  3. Meta-annotations of annotations.
  4. Attributes of annotations.
  5. Annotations are intended for compiler and tool-type software.
  6. Annotation extraction requires the use of Java reflection technology, reflection is slow, so annotations need to be used carefully with time costs.

Finally, I salute Lao Luo and Chen Ming, and use your examples to provide an argument for the topic of my blog, which is based on a technical perspective, without a hint of malice or offense.