
As Android developers, we often use annotations, the most commonly used is @Override.
Many popular frameworks use annotations as a functional mechanism, such as Spring, MyBatis, etc., which are commonly used in Java. , Butterknife, for example, is an annotation-based framework.
but do we really understand the nature of annotations?
How to customize and use it? How does it work? This article will give a comprehensive introduction.
1. Definition of Annotation
Java annotations (Annotation) are used to provide metadata for Java code.
As metadata, annotations do not directly affect your code execution, but some types of annotations can be used for this purpose.
Java annotations were added to Java starting with Java5.
2. Annotation type
1. Meta annotations
Meta-annotations, as the name implies, can be understood as annotations of annotations, which are used in annotations to facilitate us to use annotations to achieve the desired functions.
There are five kinds of meta-annotations:
- @Retention
- @Target
- @Document
- @Inherited
- @Repeatable (added in JDK1.8).
@Retention
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation {
}
Code language: PHP (php)
@Retention
means that the annotation stage is retained in the source code (compile time), bytecode (class loading) or runtime (running in the JVM).
Use the enumeration RetentionPolicy
in the @Retention
annotation to represent the retention policy during the annotation retention period:
@Retention(RetentionPolicy.SOURCE) , the annotation only exists in the source code, not in the class bytecode file
@Retention(RetentionPolicy.CLASS), the default retention policy, annotations will exist in the class bytecode file, but cannot be obtained at runtime
@Retention(RetentionPolicy.RUNTIME), the annotation will exist in the class bytecode file and can be obtained through reflection at runtime
Code language: CSS (css)
@Target
@Target({ElementType.FIELD,ElementType.METHOD})
public @interface MyAnnotation {
}
Code language: CSS (css)
@Target
meta-annotation is used to indicate that the scope of our annotations is more specific, which can be classes, methods, method parameter variables, etc., and also expresses the effect through the enumeration class ElementType
type.
@Target(ElementType.TYPE) Function interface, class, enumeration, annotation
@Target(ElementType.FIELD) works on attribute fields, enumeration constants
@Target(ElementType.METHOD) action method
@Target(ElementType.PARAMETER) Action method parameters
@Target(ElementType.CONSTRUCTOR) role constructor
@Target(ElementType.LOCAL_VARIABLE) acts on local variables
@Target(ElementType.ANNOTATION_TYPE) acts on the annotation (this attribute is used in the @Retention annotation)
@Target(ElementType.PACKAGE) works on packages
@Target(ElementType.TYPE_PARAMETER) acts on type generics, that is, generic methods, generic classes, generic interfaces (added by jdk1.8)
@Target(ElementType.TYPE_USE) type is used. It can be used to mark any type except class (joined by jdk1.8).
Generally, the ElementType.TYPE type is commonly used.
Code language: PHP (php)
@Documented
@Documented
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation {
}
Code language: PHP (php)
@Documented
is used to include the elements in the annotation into the Javadoc.
@Inherited
@Documented
@Inherited
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface MyAnnotation {
}
Code language: PHP (php)
An annotation annotated by @Inherited
modifies a parent class, and its subclasses also inherit the parent class’s annotations (subclasses can be other annotation modifications).
@MyAnnotation
public class FatherClass {
}
public class SonClass extends FatherClass {
}
public class test {
public static void main(String[] args){
Class<SonClass> sonClass = SonClass.class;
MyAnnotation annotation =sonClass.getAnnotation(MyAnnotation.class);
}
}
Code language: JavaScript (javascript)
In the above example, the parent class has an inheritable annotation, and the annotation does not modify the subclass, but the subclass obtains the Mynnotation annotation successfully, indicating that the subclass inherits the MyAnnotation in the parent class.
@Repeatable
The annotation modified by @Repeatable
can be applied to an object multiple times at the same time, but each time the applied annotation can represent a different meaning.
Introduced after Java 1.8, the function annotation can take multiple values.
The following example illustrates its definition.
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface RoleContainer {
Role[] value();
}
@Repeatable(RoleContainer.class)
@Retention(RetentionPolicy.RUNTIME)
public @interface Role {
String role() default "";
}
@Role(role = "CEO")
@Role(role = "Father")
@Role(role = "husband")
@Role(role = "son")
public class Man {
}
Code language: CSS (css)
2. Java built-in annotations
Definition: the annotations that have been implemented in Java
There are five types of built-in annotations in Java, including:
- @Deprecated : Deprecated annotation to mark deprecated & discarded elements (classes, methods, etc.)
- @Override : Override annotation, used to mark that the method needs to be overridden by subclasses
- @SuppressWarnings : Suppress warnings annotation, used to mark elements that will prevent the compiler from issuing warnings
- @SafeVarargs : parameter safe type annotation, used to remind developers not to do unsafe operations with parameters & prevent the compiler from generating unchecked warnings, introduced after Java 1.7
@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!
}
Code language: JavaScript (javascript)
@FunctionalInterface : functional interface annotation, functional interface = 1 common interface with 1 method, a new feature introduced after Java 1.8
@FunctionalInterface
public interface Runnable {
public abstract void run();
}
Code language: PHP (php)
3. Custom annotations
Definition: Developer Custom Annotations.
The next section describes how to customize annotations, and learn about annotation attributes and how to get the attributes of annotations.
3. The use of annotations
1. Define annotations
The form of definition annotation is similar to the interface, just add @ in front of the interface:
public @interface Role {
String role() default "";
}
Code language: PHP (php)
2. Annotation properties
The essence of annotation is an Annotation interface.
public interface Annotation {
boolean equals(Object obj);
int hashCode();
Class<? extends Annotation> annotationType();
}
Code language: HTML, XML (xml)
Through the above source code, we know that the annotation itself is a sub-interface of the Annotation interface,
there can be attributes and methods in the annotation, but the attributes in the interface are static final
,
which is meaningless for the annotation, and when we define the interface the method is equivalent to the attribute of the annotation,
that is why the annotation only has attribute member variables, it is the method of the interface, which is why the member variable has parentheses.
Unlike the interface, we can assign values to the member variables in the parentheses of the annotation.
public @interface Role {
String role() default "";
int id();
}
Role(role="father" ,id =1)
Role("father")
Code language: PHP (php)
Annotation attribute types can have the types listed below:
- basic data type
- String
- enum type
- Annotation type
- Class type
- One-dimensional array types of the above types
3. Use annotations
This annotation can be used by adding @annotation_name before the class/member variable/method definition.
@Role(role = "CEO")
public class Tony {
}
Code language: PHP (php)
4. Get annotations
The purpose of using annotations is to obtain annotation attribute values.
How to get annotations? –it is based on Java’s reflection technology.
It will take a certain amount of time to use Java reflection, so consider the impact on performance before using the run annotation
How to get annotations:
public boolean isAnnotationPresent(Class<? extends Annotation> annotationClass) {
return GenericDeclaration.super.isAnnotationPresent(annotationClass);
}
public <A extends Annotation> A getAnnotation(Class<A> annotationClass) {
Objects.requireNonNull(annotationClass);
return (A) annotationData().annotations.get(annotationClass);
}
public Annotation[] getAnnotations() {
return AnnotationParser.toArray(annotationData().annotations);
}
Code language: PHP (php)
Example of getting annotations and annotation properties:
@Retention(RetentionPolicy.RUNTIME)
public @interface Role {
String role() default "";
int id();
}
@Role(role = "CEO", id = 1)
public class Tony {
@Role(role = "teacher", id = 2)
public String son;
@Role(role = "doctor", id = 3)
public String getDaughter() {
return "daughter is doctor";
}
}
public class TestAnnotation {
public static void test() {
boolean isRoleAnnotation = Tony.class.isAnnotationPresent(Role.class);
Log.d(TAG, "tony is decorated by RoleAnnotation:" + isRoleAnnotation);
Role roleAnnotation = Tony.class.getAnnotation(Role.class);
if (roleAnnotation != null) {
Log.d(TAG, "tony role is " + roleAnnotation.role());
}
Class<Tony> tony = Tony.class;
try {
Field field = tony.getField("son");
roleAnnotation = field.getAnnotation(Role.class);
if (roleAnnotation != null) {
Log.d(TAG, "field role is " + roleAnnotation.role());
}
Method method = tony.getDeclaredMethod("getDaughter");
roleAnnotation = field.getAnnotation(Role.class);
if (roleAnnotation != null) {
Log.d(TAG, "method role is " + roleAnnotation.role());
}
} catch (Exception e) {
}
}
}
Code language: JavaScript (javascript)
print result:
D/TestAnnotation: tony is decorated by RoleAnnotation:true
D/TestAnnotation: tony role is CEO
D/TestAnnotation: field role is teacher
D/TestAnnotation: method role is teacher
Code language: HTTP (http)
The Use scenarios of annotations
According to the Retention attribute of the annotation, its use can be divided into 3 scenarios:
- Provide information to the compiler: The compiler can use annotations to detect errors or warnings and print out logs.
- Processing during compilation phase: Software tools can be used to use annotation information to automatically generate code, documentation, or do other corresponding automatic processing.
- Runtime processing: Some annotations can accept code extraction when the program is running, and automatically do the corresponding operations.
Scenario 1 Test Code
For example, the well-known testing framework JUnit = uses annotations for code testing.
public class ExampleUnitTest {
@Test
public void Method() throws Exception {
...
}
}
Code language: PHP (php)
Scenario 2: Decoupling & Simplifying Code to Improve Development Efficiency
ButterKnife, the well-known IOC framework in Android development, reduces a lot of repetitive code.
public class TestActivity extends AppCompatActivity {
@BindView(R.id.tvTest)
TextView tvTest;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_test);
ButterKnife.bind(this);
}
Code language: JavaScript (javascript)
The awesome Http network access framework Retrofit uses annotations to describe network request parameters:
public interface UserService {
@GET("users/all")
Call<List<UserInfo>> listUsers();
}
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("https://xxx.com/")
.build();
UserService userService = retrofit.create(UserService.class)
Call<Response<List<UserInfo>>> call = userService.listUsers();
Code language: JavaScript (javascript)
5. How annotations work
Compile-time processing
Compile-time processing requires the use of APT technology, which provides a set of compile-time annotation processing procedures.
The annotations of .java files are scanned at compile time and passed to the annotation processor.
The annotation processor can generate new .java files according to the annotations. These new .java files are compiled by javac together with the original .java

An annotation processor is a tool for processing annotations at javac compile time. You can create annotation processors and register them. At compile time, the processors you create take Java code as input and generate .java files as output.
Annotation processors cannot modify existing Java classes, they can only generate new Java classes.
Runtime
processing Runtime annotations are processed through reflection technology. Runtime annotations are to obtain attributes and methods decorated with annotations through reflection
6. Summary
This article comprehensively summarizes the definition and types of annotations with examples
Annotations are very common in our development, and using annotations is a skill we must master.
The use of annotations can improve development efficiency and write elegant code, but it should also be noted that running annotations will bring performance problems.
We need to deeply understand the principles of annotations and balance their use.