Self-built Annotation :Format and Essence

This is the video version of the tutorial:

Self built Java Annotation: Format & Essence

After learning about annotations built by others, we might wonder if we can also built some annotations by our own. After all, the beauty of learning programming is to build your own world.

However, we have no idea how to program an annotation ourselves. So what do we do? We simulate. So first let’s see how is the built-in annotation is programed.

Format of annotation

We can jump into the source code clicking the @Overridewhile holding ⌘command. Here is the source code for @Override

@Override

1
2
3
4
5
6
7
8
9
/*
......
* @jls 9.6.4.4 @Override
* @since 1.5
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.SOURCE)
public @interface Override {
}

Here we found that there are two part of the code. A chunk of code like this:

1
2
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.SOURCE)

And another chunk of code like this:

1
2
public @interface Override {
}

@Deprecated

Now let’s see the source code for @Deprecated:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
/**
.......
*/
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(value={CONSTRUCTOR, FIELD, LOCAL_VARIABLE, METHOD, PACKAGE, MODULE, PARAMETER, TYPE})
public @interface Deprecated {
/**
....
*/
String since() default "";
/**
....
*/
boolean forRemoval() default false;

It seems like that the definition of annotations is divided into two part: upper part with a bunch of other annotations; and a lower part with public @interface ....

To define an annotation:

We are correct, there are two parts. The annotation above public @interface .... is called “Meta annotation”, which means the annotation for annotation. Does that sound familiar? Yeah, we saw it in the last video in the Java Annotation Wikipedia Page, which is the thing that we would ignore for “now”.

Create our own annotations:

Now we do not care about the meta annotation, will still delay that for now.

Yet for the following part, we always see something like public @interface ...., that is essentially how we build an annotation. Alright, since we have revealed the mysterious vail on the top of the annotation, let’s build one ourselves.

1
public @interface RayAnno {}

Let’s try it out.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
/**
* @author : Ray Li
* @created : 13/31/3033, 25:61
* @description :
*/
@RayAnno
public class RayAnnoTest {
@RayAnno
int age;

@RayAnno
String name;

@RayAnno
public void testMethod1() {}

@RayAnno
public String testMethod2(int a, int b) {
return "";
}

@RayAnno
public void testMethod3() {}
}

We found that we could add my own annotation to wherever we want.

What is behind annotation

Now we’ve known how the define an annotation, though don’t know what that can be used for. But we are human. WE ARE CURIOUS. We want to know how this is working, just like we want to know others’ secrets.

We can do this by decompile. The java file will eventually be compiled to a Byte-code file, and we can decompile it to see what is really behind the scene.

So how do we do it?

We have the code:

1
public @interface RayAnno {}

and a file RayAnno.java

We do the following to compile .java file, we will get a RayAnno.classfile, which is the Byte-code file aforementioned.

1
% javac RayAnno.java

Then we do the following commend to disassemble the RayAnno.class

1
% javac RayAnno.class

We get

1
2
3
Compiled from "RayAnno.java"
public interface RayAnno extends java.lang.annotation.Annotation {
}

which means that a “new” .java file was generated, which includes:

1
2
public interface RayAnno extends java.lang.annotation.Annotation {
}

How amazing!

Thus, we found the essence of the annotation. Which is public interface RayAnno extends java.lang.annotation.Annotation {}.

public interface RayAnno extends java.lang.annotation.Annotation {}

This line of code reveals that we are actually creating a new interface when we create an annotation. Furthermore, this interface extends Annotation interface under package java.lang.annotation.

Let’s take a trip into this intriguing Annotation interface

Here is the API documentation. We found the following:

This just means that this interface is the root interface for all annotations.

We also see some built in methods, which we will talk about later on.

Now we have known that an annotation is simply an interface. Thus, it makes sense to induce that what can be defined in interfaces should be able to be defined in the annotation. And now we are going to talk about some characteristic about annotations.

Annotation’s content

So what do we talk about in the interface? Methods. (Attributes are kinda useless in this case) Let’s take a look about the methods in annotations.

We can code some abstract method in annotations as:

1
2
3
4
5
6
7
8
/**
* @author : Ray Li
* @created : 13/31/3033, 25:61
* @description :
*/
public @interface RayAnno {
public String show();
}

We can add an abstract of course:

1
2
3
4
5
6
7
8
/**
* @author : Ray Li
* @created : 13/31/3033, 25:61
* @description :
*/
public @interface RayAnno {
public abstract String show();
}

We call those methods in annotation “attributes” of annotation. There are some special features about these attributes, which we will talk about soon.


Self-built Annotation :Format and Essence
http://blog.slray.com/2023/02/04/Java-Annotation-build-annotations-by-yourself/
Author
Sirui Ray Li
Posted on
February 4, 2023
Licensed under