Java 注解 Annotation

更多 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());
        }
    }
}

你可能感兴趣的:(Java 注解 Annotation)