如何自定义一个注解并获取注解

注解是跟多java 架构经常用到的,那如何自己定义一个注解,今天我们学习注解的定义和使用。

所有的注解类型都继承自这个普通的接口(Annotation)。

元注解

『元注解』是用于修饰注解的注解

通常有以下几种

  • @Target:注解的作用目标
  • @Retention:注解的生命周期
  • @Documented:注解是否应当被包含在 JavaDoc 文档中
  • @Inherited:是否允许子类继承该注解

其中,@Target 用于指明被修饰的注解最终可以作用的目标是谁,也就是指明,你的注解到底是用来修饰方法的?修饰类的?还是用来修饰字段属性的。

我们可以通过以下的方式来为这个 value 传值:

@Target(value = {ElementType.FIELD})

被这个 @Target 注解修饰的注解将只能作用在成员字段上,不能用于修饰方法或者类。其中,ElementType 是一个枚举类型,有以下一些值:

  • ElementType.TYPE:允许被修饰的注解作用在类、接口和枚举上
  • ElementType.FIELD:允许作用在属性字段上
  • ElementType.METHOD:允许作用在方法上
  • ElementType.PARAMETER:允许作用在方法参数上
  • ElementType.CONSTRUCTOR:允许作用在构造器上
  • ElementType.LOCAL_VARIABLE:允许作用在本地局部变量上
  • ElementType.ANNOTATION_TYPE:允许作用在注解上
  • ElementType.PACKAGE:允许作用在包上

@Retention 用于指明当前注解的生命周期,它的基本定义如下:

image

同样的,它也有一个 value 属性:

@Retention(value = RetentionPolicy.RUNTIME

这里的 RetentionPolicy 依然是一个枚举类型,它有以下几个枚举值可取:

  • RetentionPolicy.SOURCE:当前注解编译期可见,不会写入 class 文件
  • RetentionPolicy.CLASS:类加载阶段丢弃,会写入 class 文件
  • RetentionPolicy.RUNTIME:永久保存,可以反射获取

@Retention 注解指定了被修饰的注解的生命周期,一种是只能在编译期可见,编译后会被丢弃,一种会被编译器编译进 class 文件中,无论是类或是方法,乃至字段,他们都是有属性表的,而 JAVA 虚拟机也定义了几种注解属性表用于存储注解信息,但是这种可见性不能带到方法区,类加载时会予以丢弃,最后一种则是永久存在的可见性。

剩下两种类型的注解我们日常用的不多,也比较简单,这里不再详细的进行介绍了,你只需要知道他们各自的作用即可。@Documented 注解修饰的注解,当我们执行 JavaDoc 文档打包时会被保存进 doc 文档,反之将在打包时丢弃。@Inherited 注解修饰的注解是具有可继承性的,也就说我们的注解修饰了一个类,而该类的子类将自动继承父类的该注解。

现在我们来自己定义一个注解类,目的是用它来标记某些字段。

@Documented
@Retention(RetentionPolicy.RUNTIME) //注释由编译器记录在类文件中,并由*在运行时由VM保留,因此可以通过反射方式读取它们
@Target(ElementType.FIELD) //  字段声明(包括枚举常量)
public @interface AnTest {
    int number();
}

现在我们找个类来应用下:

public class TestMode {
    @AnTest(number = 3)

    private int age;
    @AnTest(number = 2)

    String name;

    @AnTest(number = 1)

    int length;
    public TestMode() {
        if (false) {
        }
    }

    public TestMode(int age, String name, int length) {
        this.age = age;
        this.name = name;
        this.length = length;
    }

    public int getLength() {
        return length;
    }

    public void setLength(int length) {
        this.length = length;
    }


    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getName() {
        return name;
    }

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

    @Override
    public String toString() {
        return "TestMode{" +
                "age=" + age +
                ", name='" + name + '\'' +
                ", length=" + length +
                '}';
    }
}

测试类:

public static void main(String args[]) {
    TestMode testMode = new TestMode(30, "明", 170);

    Class cla = testMode.getClass();

    Field[] fields = cla.getDeclaredFields();
    for (Field field : fields) {
        AnTest anTest = field.getAnnotation(AnTest.class);
        System.out.println(field.getName() +":自定义注解 :"+ anTest.number());
    }
}

结果:

age:自定义注解 :3
name:自定义注解 :2
length:自定义注解 :1

这样我们就通过反射获取到了我们自定义的注解。

参考:

https://blog.csdn.net/HaHa_Sir/article/details/81331437

 

 

 

 

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章