Java 注解(Annotation)使用方法归纳

简介

注解是从JDK5开始支持,是Java对元数据的一种特殊支持。与注释有一定区别,
可以理解为代码上的特殊标记,通过这些标记我们可以在编译,类加载,运行等
程序类的生命周期内被读取、执行相应的处理。通过注解开发人员可以在不改变
原有代码和逻辑的情况下在源代码中嵌入补充信息。注解是Java语言的一种强大的功能。

自定义注解

编写自定义注解

  • 注解的定义修饰符为@interface
  • 注解中可以添加成员变量,成员变量以方法的形式定义
  • 需要使用@Retention注解来规定它的生命周期(编译期间、运行时等)
  • 需要使用@Target注解来规定它的适用范围(类型、方法、字段、方法参数等)

例子一

代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import java.lang.annotation.*;

@Inherited
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD,
ElementType.CONSTRUCTOR,
ElementType.FIELD,
ElementType.PARAMETER,
ElementType.TYPE,
ElementType.ANNOTATION_TYPE})
public @interface TestAnnotation {

String value();

}

说明

  • @Inherited注解规定了这个自定义注解是可以被继承的。(父类修饰子类继承)
  • 注解定义中 String value(); 通过方法的方式定义了注解的成员变量value

使用注解进行修饰

  • 使用TestAnnotation来给类、成员变量添加注解
  • value命名的成员变量可以直接以参数的形式赋值。

代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
@TestAnnotation("Class Student")
public class Student {

@TestAnnotation("constance field")
public static final String CLASS_NAME = "Student";
@TestAnnotation("field")
private String name;


public Student(String name) {
this.name = name;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}
}

例子二

  • 使用 default ${value} 的形式可以定义成员变量是否需要默认值。

代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import java.lang.annotation.*;

@Inherited
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD,
ElementType.CONSTRUCTOR,
ElementType.FIELD,
ElementType.PARAMETER,
ElementType.TYPE,
ElementType.ANNOTATION_TYPE})
public @interface TestAnnotationTwo {

String message();
String[] names() default {};

}

说明

  • 注解定义中 String message(); String[] names(); 通过方法的方式定义了注解的成员变量message和names,其中names为String数组

使用注解进行修饰

  • 非value命名的成员变量需要通过 fieldName = value 来进行赋值
  • 注解中可以为空(具有默认值)的成员变量可以不赋值

代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
@TestAnnotationTwo(message = "Hello!")
public class StudentTwo {

@TestAnnotationTwo(message = "Hi!", names = {"holo", "la"})
private String id;

@TestAnnotationTwo(message = "yes")
private String name;

public String getId() {
return id;
}

public void setId(String id) {
this.id = id;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}
}

自定义注解处理

一般定义好注解的生命周期、成员变量之后,还需要针对注解编写相应的处理程序,获取程序的元数据。

注解定义如下

代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
import java.lang.annotation.*;

@Inherited
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD,
ElementType.CONSTRUCTOR,
ElementType.FIELD,
ElementType.PARAMETER,
ElementType.TYPE,
ElementType.ANNOTATION_TYPE})
public @interface TestAnnotation {

String value();
}

使用自定义注解修饰代码

例子中的Student通过@TestAnnotation注解分别修饰了类、字段、方法以及方法参数

代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
@TestAnnotation("Class Student")
public class Student {
@TestAnnotation("constance field")
public static final String CLASS_NAME = "Student";

@TestAnnotation("field")
private String name;

@TestAnnotation("Constructor")
public Student(String name) {
this.name = name;
}

@TestAnnotation("getter")
public String getName() {
return name;
}

@TestAnnotation("setter")
public void setName(String name) {
this.name = name;
}

@TestAnnotation("public method")
public void printName() {
System.out.println(name);
}

@TestAnnotation("public method with parameter")
public void printName(@TestAnnotation("parameter") String name) {
System.out.println(name);
}
}

编写处理程序获取元数据

获取类(type)上的注解及其变量value值

代码如下:

1
2
3
4
5
6
7
8
9
10
11
public void learnClassAnnotation() {
Class<?> clazzStudent = Student.class;
for (Annotation annotation : clazzStudent.getAnnotations()) {
if (annotation instanceof TestAnnotation) {
System.out.println(((TestAnnotation) annotation).value());
}
if (annotation.annotationType() == TestAnnotation.class) {
System.out.println(((TestAnnotation) annotation).value());
}
}
}

结果如下:

1
2
Class Student
Class Student

获取字段(field)上的注解及其变量value值

代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public void learnFieldAnnotation() {
Class<?> clazz = Student.class;
List<Field> fields = Arrays.asList(clazz.getDeclaredFields());
fields.forEach(field -> {
System.out.println("\n\n------------------------field " + field.getName());
for (Annotation annotation : field.getAnnotations()) {
if (annotation instanceof TestAnnotation) {
System.out.println(((TestAnnotation) annotation).value());
}
if (annotation.annotationType() == TestAnnotation.class) {
System.out.println(((TestAnnotation) annotation).value());
}
}
});

}

结果如下:

1
2
3
4
5
6
7
8
------------------------field CLASS_NAME
constance field
constance field


------------------------field name
field
field

获取构造器(constructor)上的注解及其变量value值

代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public void learnConstructorAnnotation() {
Class<?> clazz = Student.class;
List<Constructor<?>> constructors = Arrays.asList(clazz.getDeclaredConstructors());
constructors.forEach(constructor -> {
System.out.println("\n\n------------------------constructor " + constructor.getName());
for (Annotation annotation : constructor.getAnnotations()) {
if (annotation instanceof TestAnnotation) {
System.out.println(((TestAnnotation) annotation).value());
}
if (annotation.annotationType() == TestAnnotation.class) {
System.out.println(((TestAnnotation) annotation).value());
}
}
});
}

结果如下:

1
2
3
------------------------constructor Student
Constructor
Constructor

获取方法(method)上的注解及其变量value值

代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public void learnMethodAnnotation() {
Class<?> clazz = Student.class;
List<Method> methods = Arrays.asList(clazz.getMethods());
methods.forEach(method -> {
System.out.println("\n\n------------------------method " + method.getName());
for (Annotation annotation : method.getAnnotations()) {
if (annotation instanceof TestAnnotation) {
System.out.println(((TestAnnotation) annotation).value());
}
if (annotation.annotationType() == TestAnnotation.class) {
System.out.println(((TestAnnotation) annotation).value());
}
}
});
}

结果如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
------------------------method getName
getter
getter


------------------------method setName
setter
setter


------------------------method printName
public method
public method


------------------------method printName
public method with parameter
public method with parameter


------------------------method wait


------------------------method wait


------------------------method wait


------------------------method equals


------------------------method toString


------------------------method hashCode


------------------------method getClass


------------------------method notify


------------------------method notifyAll

获取方法参数(parameter)上的注解及其变量value值

代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public void learnParameterAnnotation() {
Class<?> clazz = Student.class;
List<Method> methods = Arrays.asList(clazz.getMethods());
for (Method method : methods) {
System.out.println("\n\n-----------------------------------------------method " + method.getName());
for (Parameter parameter : method.getParameters()) {
System.out.println("------------------------parameter " + parameter.getName());
for (Annotation annotation : parameter.getAnnotations()) {
if (annotation instanceof TestAnnotation) {
System.out.println(((TestAnnotation) annotation).value());
}
if (annotation.annotationType() == TestAnnotation.class) {
System.out.println(((TestAnnotation) annotation).value());
}
}
}
}
}

结果:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
-----------------------------------------------method getName


-----------------------------------------------method setName
------------------------parameter arg0


-----------------------------------------------method printName


-----------------------------------------------method printName
------------------------parameter arg0
parameter
parameter


-----------------------------------------------method wait


-----------------------------------------------method wait
------------------------parameter arg0
------------------------parameter arg1


-----------------------------------------------method wait
------------------------parameter arg0


-----------------------------------------------method equals
------------------------parameter arg0


-----------------------------------------------method toString


-----------------------------------------------method hashCode


-----------------------------------------------method getClass


-----------------------------------------------method notify


-----------------------------------------------method notifyAll

说明

通过反射方式获取Annotation[]数组之后,可以通过下面两种方式来判断此注解是否就是你自定义的注解

  1. 通过 instanceof 操作,判断annotation对象是否是自定义注解类
1
annotation instanceof TestAnnotation
  1. 通过 Annotation 的 annotationType() 方法获取到annotation对象的类型,并同自定义注解类进行比对
1
annotation.annotationType() == TestAnnotation.class

注解处理工具类

最后附上注解处理的工具类,定义了若干实用的注解处理方法,希望对朋友们有所帮助

代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
import java.lang.annotation.Annotation;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;

/**
* Created by xuyh(Johnsonmoon) at 2018/1/3 11:43.
*/
public class AnnotationUtils {
/**
* get declared annotations of the given class
*
* @param clazz given class
* @return annotations
*/
public static Annotation[] getAnnotations(Class<?> clazz) {
return clazz.getAnnotations();
}

/**
* get declared annotations of the given field
*
* @param field given field
* @return annotations
*/
public static Annotation[] getAnnotations(Field field) {
return field.getAnnotations();
}

/**
* get declared annotations of the given method
*
* @param method given method
* @return annotations
*/
public static Annotation[] getAnnotations(Method method) {
return method.getAnnotations();
}

/**
* get declared annotations of the given constructor
*
* @param constructor given constructor
* @return annotations
*/
public static Annotation[] getAnnotations(Constructor constructor) {
return constructor.getAnnotations();
}

/**
* get declared annotations of the given parameter
*
* @param parameter given parameter
* @return annotations
*/
public static Annotation[] getAnnotations(Parameter parameter) {
return parameter.getAnnotations();
}

/**
* Is field has annotation of annotationType
*
* @param field given field
* @param annotationType given annotation type
* @return true/false
*/
public static boolean hasAnnotation(Field field, Class<?> annotationType) {
Annotation[] annotations = field.getAnnotations();
if (annotations == null || annotations.length == 0)
return false;
for (Annotation annotation : annotations) {
if (annotation.annotationType() == annotationType)
return true;
}
return false;
}


/**
* Is clazz has annotation of annotationType
*
* @param clazz given clazz
* @param annotationType given annotation type
* @return true/false
*/
public static boolean hasAnnotation(Class<?> clazz, Class<?> annotationType) {
Annotation[] annotations = clazz.getAnnotations();
if (annotations == null || annotations.length == 0)
return false;
for (Annotation annotation : annotations) {
if (annotation.annotationType() == annotationType)
return true;
}
return false;
}


/**
* Is method has annotation of annotationType
*
* @param method given method
* @param annotationType given annotation type
* @return true/false
*/
public static boolean hasAnnotation(Method method, Class<?> annotationType) {
Annotation[] annotations = method.getAnnotations();
if (annotations == null || annotations.length == 0)
return false;
for (Annotation annotation : annotations) {
if (annotation.annotationType() == annotationType)
return true;
}
return false;
}


/**
* Is constructor has annotation of annotationType
*
* @param constructor given constructor
* @param annotationType given annotation type
* @return true/false
*/
public static boolean hasAnnotation(Constructor<?> constructor, Class<?> annotationType) {
Annotation[] annotations = constructor.getAnnotations();
if (annotations == null || annotations.length == 0)
return false;
for (Annotation annotation : annotations) {
if (annotation.annotationType() == annotationType)
return true;
}
return false;
}


/**
* Is parameter has annotation of annotationType
*
* @param parameter given parameter
* @param annotationType given annotation type
* @return true/false
*/
public static boolean hasAnnotation(Parameter parameter, Class<?> annotationType) {
Annotation[] annotations = parameter.getAnnotations();
if (annotations == null || annotations.length == 0)
return false;
for (Annotation annotation : annotations) {
if (annotation.annotationType() == annotationType)
return true;
}
return false;
}

/**
* Get annotation of given annotation type declared in given field.
*
* @param field given field
* @param annotationType given annotation type
* @return annotation instance
*/
public static Annotation getAnnotation(Field field, Class<?> annotationType) {
Annotation[] annotations = field.getAnnotations();
if (annotations == null || annotations.length == 0)
return null;
for (Annotation annotation : annotations) {
if (annotation.annotationType() == annotationType)
return annotation;
}
return null;
}

/**
* Get annotation of given annotation type declared in given clazz.
*
* @param clazz given clazz
* @param annotationType given annotation type
* @return annotation instance
*/
public static Annotation getAnnotation(Class<?> clazz, Class<?> annotationType) {
Annotation[] annotations = clazz.getAnnotations();
if (annotations == null || annotations.length == 0)
return null;
for (Annotation annotation : annotations) {
if (annotation.annotationType() == annotationType)
return annotation;
}
return null;
}

/**
* Get annotation of given annotation type declared in given method.
*
* @param method given method
* @param annotationType given annotation type
* @return annotation instance
*/
public static Annotation getAnnotation(Method method, Class<?> annotationType) {
Annotation[] annotations = method.getAnnotations();
if (annotations == null || annotations.length == 0)
return null;
for (Annotation annotation : annotations) {
if (annotation.annotationType() == annotationType)
return annotation;
}
return null;
}

/**
* Get annotation of given annotation type declared in given constructor.
*
* @param constructor given constructor
* @param annotationType given annotation type
* @return annotation instance
*/
public static Annotation getAnnotation(Constructor<?> constructor, Class<?> annotationType) {
Annotation[] annotations = constructor.getAnnotations();
if (annotations == null || annotations.length == 0)
return null;
for (Annotation annotation : annotations) {
if (annotation.annotationType() == annotationType)
return annotation;
}
return null;
}

/**
* Get annotation of given annotation type declared in given parameter.
*
* @param parameter given parameter
* @param annotationType given annotation type
* @return annotation instance
*/
public static Annotation getAnnotation(Parameter parameter, Class<?> annotationType) {
Annotation[] annotations = parameter.getAnnotations();
if (annotations == null || annotations.length == 0)
return null;
for (Annotation annotation : annotations) {
if (annotation.annotationType() == annotationType)
return annotation;
}
return null;
}
}