LinuxSir.cn,穿越时空的Linuxsir!

 找回密码
 注册
搜索
热搜: shell linux mysql
查看: 184|回复: 0

Java - 元注解

[复制链接]
发表于 2023-12-16 23:58:06 | 显示全部楼层 |阅读模式
元注解
上述内置注解的定义中使用了一些元注解(注解类型进行注解的注解类),在JDK 1.5中提供了4个标准的元注解:@Target,@Retention,@Documented,@Inherited, 在JDK 1.8中提供了两个元注解 @Repeatable和@Native。
# 元注解 - @TargetTarget注解的作用是:描述注解的使用范围(即:被修饰的注解可以用在什么地方) 。
Target注解用来说明那些被它所注解的注解类可修饰的对象范围:注解可以用于修饰 packages、types(类、接口、枚举、注解类)、类成员(方法、构造方法、成员变量、枚举值)、方法参数和本地变量(如循环变量、catch参数),在定义注解类时使用了@Target 能够更加清晰的知道它能够被用来修饰哪些对象,它的取值范围定义在ElementType 枚举中。
public enum ElementType {

    TYPE, // 类、接口、枚举类

    FIELD, // 成员变量(包括:枚举常量)

    METHOD, // 成员方法

    PARAMETER, // 方法参数

    CONSTRUCTOR, // 构造方法

    LOCAL_VARIABLE, // 局部变量

    ANNOTATION_TYPE, // 注解类

    PACKAGE, // 可用于修饰:包

    TYPE_PARAMETER, // 类型参数,JDK 1.8 新增

    TYPE_USE // 使用类型的任何地方,JDK 1.8 新增

}

# 元注解 - @Retention & @RetentionTargetReteniton注解的作用是:描述注解保留的时间范围(即:被描述的注解在它所修饰的类中可以被保留到何时) 。
Reteniton注解用来限定那些被它所注解的注解类在注解到其他类上以后,可被保留到何时,一共有三种策略,定义在RetentionPolicy枚举中。

public enum RetentionPolicy {

    SOURCE,    // 源文件保留
    CLASS,       // 编译期保留,默认值
    RUNTIME   // 运行期保留,可通过反射去获取注解信息
}

为了验证应用了这三种策略的注解类有何区别,分别使用三种策略各定义一个注解类做测试。
@Retention(RetentionPolicy.SOURCE)
public @interface SourcePolicy {

}
@Retention(RetentionPolicy.CLASS)
public @interface ClassPolicy {

}
@Retention(RetentionPolicy.RUNTIME)
public @interface RuntimePolicy {

}
用定义好的三个注解类分别去注解一个方法。

public class RetentionTest {

        @SourcePolicy
        public void sourcePolicy() {
        }

        @ClassPolicy
        public void classPolicy() {
        }

        @RuntimePolicy
        public void runtimePolicy() {
        }
}
通过执行 javap -verbose RetentionTest命令获取到的RetentionTest 的 class 字节码内容如下。

  1. {
  2.   public retention.RetentionTest();
  3.     flags: ACC_PUBLIC
  4.     Code:
  5.       stack=1, locals=1, args_size=1
  6.          0: aload_0
  7.          1: invokespecial #1                  // Method java/lang/Object."<init>":()V
  8.          4: return
  9.       LineNumberTable:
  10.         line 3: 0

  11.   public void sourcePolicy();
  12.     flags: ACC_PUBLIC
  13.     Code:
  14.       stack=0, locals=1, args_size=1
  15.          0: return
  16.       LineNumberTable:
  17.         line 7: 0

  18.   public void classPolicy();
  19.     flags: ACC_PUBLIC
  20.     Code:
  21.       stack=0, locals=1, args_size=1
  22.          0: return
  23.       LineNumberTable:
  24.         line 11: 0
  25.     RuntimeInvisibleAnnotations:
  26.       0: #11()

  27.   public void runtimePolicy();
  28.     flags: ACC_PUBLIC
  29.     Code:
  30.       stack=0, locals=1, args_size=1
  31.          0: return
  32.       LineNumberTable:
  33.         line 15: 0
  34.     RuntimeVisibleAnnotations:
  35.       0: #14()
  36. }
复制代码

从 RetentionTest 的字节码内容我们可以得出以下两点结论:编译器并没有记录下 sourcePolicy() 方法的注解信息;
编译器分别使用了 RuntimeInvisibleAnnotations 和 RuntimeVisibleAnnotations 属性去记录了classPolicy()方法 和 runtimePolicy()方法 的注解信息;
# 元注解 - @DocumentedDocumented注解的作用是:描述在使用 javadoc 工具为类生成帮助文档时是否要保留其注解信息。
以下代码在使用Javadoc工具可以生成@TestDocAnnotation注解信息。
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Target;

@Documented
@Target({ElementType.TYPE,ElementType.METHOD})
public @interface TestDocAnnotation {

        public String value() default "default";
}
@TestDocAnnotation("myMethodDoc")
public void testDoc() {

}
# 元注解 - @InheritedInherited注解的作用:被它修饰的Annotation将具有继承性。如果某个类使用了被@Inherited修饰的Annotation,则其子类将自动具有该注解。
我们来测试下这个注解:定义@Inherited注解:
@Inherited
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE,ElementType.METHOD})
public @interface TestInheritedAnnotation {
    String [] values();
    int number();
}
使用这个注解
@TestInheritedAnnotation(values = {"value"}, number = 10)
public class Person {
}

class Student extends Person{
        @Test
    public void test(){
        Class clazz = Student.class;
        Annotation[] annotations = clazz.getAnnotations();
        for (Annotation annotation : annotations) {
            System.out.println(annotation.toString());
        }
    }
}
输出xxxxxxx.TestInheritedAnnotation(values=[value], number=10)
即使Student类没有显示地被注解@TestInheritedAnnotation,但是它的父类Person被注解,而且@TestInheritedAnnotation被@Inherited注解,因此Student类自动有了该注解。# 元注解 - @Repeatable (Java8)@Repeatable请参考Java 8 - 重复注解# 元注解 - @Native (Java8)使用 @Native 注解修饰成员变量,则表示这个变量可以被本地代码引用,常常被代码生成工具使用。对于 @Native 注解不常使用,了解即可
------

原文链接:https://pdai.tech/md/java/basic/java-basic-x-annotation.html

您需要登录后才可以回帖 登录 | 注册

本版积分规则

快速回复 返回顶部 返回列表