更多 Java 高级知识方面的文章,请参见文集《Java 高级知识》
Java 注解 Annotation 的用处:
- 编写文档
- 代码分析
- 编译检查
元注解
-
Target 说明了注解所修饰的对象范围
使用方式:@Target(ElementType.TYPE)
-
ElementType.TYPE
:Class, interface (including annotation type), or enum declaration -
ElementType.FIELD
: -
ElementType.METHOD
: -
ElementType.PARAMETER
: -
ElementType.CONSTRUCTOR
: -
ElementType.LOCAL_VARIABLE
: -
ElementType.ANNOTATION_TYPE
: -
ElementType.PACKAGE
: -
ElementType.TYPE_PARAMETER
:Java8 开始支持 -
ElementType.TYPE_USE
:Java8 开始支持
-
-
Retention 说明了注解所保留的时间
使用方式:@Retention(RetentionPolicy.SOURCE)
-
RetentionPolicy.SOURCE
:该注解只保留在源码中,编译时编译器会去除该注解 -
RetentionPolicy.CLASS
:该注解会保留在源码和编译后的二进制代码中,但不会保留在 JVM 中。(默认方式) -
RetentionPolicy.RUNTIME
:该注解会保留在源码和编译后的二进制代码中,也会在运行时保留在 JVM 中。因此可以在运行时通过反射 API 来获取注解的信息。
-
-
Documented 在生成 JavaDoc 的时候,模式是不包含注解的,但是如果注解被 @Documented 修饰,则生成的文档就包含该注解
使用方式:@Documented
-
Inherited 若该注解被用于修饰 class,则该注解将自动应用于该 class 的子类
使用方式:@Inherited
元注解自身也是注解,例如:
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Target {
/**
* Returns an array of the kinds of elements an annotation type
* can be applied to.
* @return an array of the kinds of elements an annotation type
* can be applied to
*/
ElementType[] value();
}
自定义注解
使用 @interface
来定义注解。示例如下:
public class Annotation_Test {
public static void main(String[] args) throws Exception {
MyStudent std = new MyStudent();
Class clazz = std.getClass();
MyAnnotation annotation = (MyAnnotation) clazz.getAnnotation(MyAnnotation.class);
System.out.println(annotation.name());
System.out.println(annotation.age());
}
}
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@interface MyAnnotation {
String name();
int age();
}
@MyAnnotation(name = "Tom", age = 20)
class MyStudent {
}
Java8 新增了一个元注解 @Repeatable
在 Java 8 之前也有重复使用注解的解决方案,但可读性不是很好。
例如我们有两种人物:
- 经理
Manager
,拥有读写的权限 - 普通员工
Staff
,只拥有读的权限
首先自定义注解 Authority
:
@Retention(RetentionPolicy.RUNTIME)
public @interface Authority {
String role();
}
随后自定义注解 Authorities
,包含 Authority
数组:
@Retention(RetentionPolicy.RUNTIME)
public @interface Authorities {
Authority[] value();
}
接下来分别定义经理 Manager
和 普通员工 Staff
,以数组的形式传入多个权限 Authority
自定义注解:
@Authorities({@Authority(role = "Read"), @Authority(role = "Write")})
public class Manager {
}
@Authorities({@Authority(role = "Read")})
public class Staff {
}
最后我们可以通过如下的方式分别获得两种人物的权限:
public class ParseAuthority {
public static void main(String[] args) {
Authorities authorities = Manager.class.getAnnotation(Authorities.class);
for (Authority authority : authorities.value()) {
System.out.println(authority.role());
}
authorities = Staff.class.getAnnotation(Authorities.class);
for (Authority authority : authorities.value()) {
System.out.println(authority.role());
}
}
}
在 Java 8 之后,可以使用如下的方式:
使用 @Repeatable
原注解修饰 Authority
自定义注解:
@Repeatable(value = Authorities.class)
@Retention(RetentionPolicy.RUNTIME)
public @interface Authority {
String role();
}
自定义注解 Authorities
不用修改。
接下来通过如下的形式定义经理 Manager
和 普通员工 Staff
:
@Authority(role = "Read")
@Authority(role = "Write")
public class Manager {
}
@Authority(role = "Read")
public class Staff {
}
最后我们可以通过如下的方式分别获得两种人物的权限:
public class ParseAuthority {
public static void main(String[] args) {
Authority[] authorities = Manager.class.getAnnotationsByType(Authority.class);
for (Authority authority : authorities) {
System.out.println(authority.role());
}
authorities = Staff.class.getAnnotationsByType(Authority.class);
for (Authority authority : authorities) {
System.out.println(authority.role());
}
}
}