-
What are annotations?
Java annotations, also known as Java annotations, is an Annotation mechanism introduced in JDK5.0. For example, common @override and @Deprecated are annotations. Annotations can be added to classes, methods, member variables, etc., in a manner of “tagging” them.
-
How are annotations defined?
Public @interface {} looks similar to the interface definition except for the @ symbol: public interface interface name annotation: public @interface annotation name
public @interface lkx {
}
Copy the code
-
How are annotations used?
For example, we can define “class, member variable, member method” as follows:
@lkx
public class Test {
@lkx
private int num;
@lkx
public static void main(String[] args) {
System.out.println("hello"); }}Copy the code
-
Think about it
Now that the annotation is defined and used, I don’t want to define it on the class or on the member methods, I just want to define it on the member methods. How can I make the annotation only define it on the method, and get an error if it is defined elsewhere?Desired effect:
This is where meta-annotations are used to limit the scope.
-
Yuan notes
A meta-annotation is an annotation defined on an annotation. There are four meta-annotations in Java: @target @Retention @Documented @inherited
-
@Target
The @target is used to describe the scope of the definition of an annotation and to limit the types of elements defined by the annotation.
parameter | role |
---|---|
ElementType.ANNOTATION_TYPE | Can be applied to annotation types |
ElementType.CONSTRUCTOR | Can be applied to constructors |
ElementType.FIELD | Can be applied to fields or properties |
ElementType.LOCAL_VARIABLE | Can be applied to local variables |
ElementType.METHOD | Can be applied to method level annotations |
ElementType.PACKAGE | Can be applied to package declarations |
ElementType.PARAMETER | Parameters that can be applied to a method |
ElementType.TYPE | Can be applied to any element of a class |
Since we want to restrict definitions to only member variables, we should use elementType.field
@Target(ElementType.FIELD)
public @interface lkx {
}
Copy the code
But what if we want to define both member variables and member methods? Multiple arguments need only be enclosed in curly braces and separated by commas
@Target({ElementType.FIELD,ElementType.METHOD})
public @interface lkx {
}
Copy the code
Now only the annotations defined on the class report errors
-
@Retention
@Retention is used to define the lifetime of annotations, which can also be interpreted as how they are stored.
parameter | role |
---|---|
RetentionPolicy.SOURCE | The annotations for the tag remain only at the source level and are ignored by the compiler |
RetentionPolicy.CLASS | The annotations for the tag are retained by the compiler at compile time, but ignored by the Java Virtual Machine (JVM) |
RetentionPolicy.RUNTIME | The annotations for the tag are retained by the JVM, so the runtime environment can use it |
The following two meta-annotations are not used much and will not be explained in detail
-
@Documented
The @Documented is used to describe whether to retain the annotation information for the help document when it is generated.
-
@Inherited
@inherited is used to describe whether the note it decorates is Inherited.
-
Annotation element
Above we just defined an annotation, but it does not pass any information, it is just a tag. Now let’s see how to define parameters for an annotation:
@Target({ElementType.FIELD,ElementType.METHOD})
@Retention(RetentionPolicy.SOURCE)
public @interface lkx {
String name(a) default"Zhang"; // You can use default to define a default value
int age(a);
}
Copy the code
Now let’s look at how to pass parameters:
public class Test {
// Name has a default value
@lkx(name = "@lkx ",age = 18)
private int num;
public static void main(String[] args) {
System.out.println("hello"); }}Copy the code
-
In actual combat
Now that the annotations are defined and the parameters are passed in, you are wondering what the annotations are for… Now we have a small requirement to assign the parameter passed in the annotation to the member variable. Such as:
@lkx(name = "@lkx ",age = 18)
private int num; //num is not assigned and is equal to 0Num = after the assignment18
Copy the code
Notes:
- The following code needs to use reflection, if you don’t know it, you can read my previous articles.
- Since we need to use reflection to get annotations, @Retention needs to be defined as retentionPolicy.runtime
Implementation code:
@Target({ElementType.FIELD,ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface lkx {
String name(a) default"Zhang";
int age(a);
}
Copy the code
public class Test {
// Name has a default value
@lkx(name = "@lkx ",age = 18)
private static int num;
@lkx(name = "王五",age = 38) @lkx(name = "王五",age = 38)
private static int age;
public static void main(String[] args) throws InstantiationException, IllegalAccessException {
System.out.println("Before assignment: num:" + num+" age: "+age);
// Get the bytecode of the class
Class<Test> testClass = Test.class;
// Get all member variables
for (Field declaredField : testClass.getDeclaredFields()) {
// Check for @lkx annotation on the member variable
if (declaredField.isAnnotationPresent(lkx.class)) {
lkx annotation = declaredField.getAnnotation(lkx.class);
// Get the value of age in the annotation
int age = annotation.age();
declaredField.set(testClass.newInstance(),age);
}
}
System.out.println("Num:" + num+" age: "+age); }}Copy the code
Running result:
Before assignment: num:0 age: 0Value: num:18 age: 38
Copy the code
-
thinking
If you are a friend of Android development, do you think the actual combat is familiar? If this doesn’t look familiar, look at the following code:
@BindView(R.id.groupChat)
Button mGroupChat;
@BindView(R.id.privateChat)
Button mPrivateChat;
Copy the code
With this in mind, you should be able to easily write a dynamic findViewById framework with annotations. However, it is not recommended to use it in projects because reflection can affect code execution efficiency. If you want to do this efficiently, I recommend to see how the Butterknife framework source code is implemented.