java自定义注解

参考博客:https://blog.csdn.net/briblue/article/details/73824058

感觉这篇文章写得非常好,讲的很清楚明白,易于理解;例子也很不错,做个记录:

代码:

package com.cy.test;

import java.lang.annotation.*;
import java.lang.reflect.Field;
import java.lang.reflect.Method;

/**
 * 自定义注解测试类
 */
@MyAnnotation(id = 100, msg = "hello annotation")
public class TestAnnotation{

    @Check("hi")
    private int a;

    @Perform
    public void testMethod(){

    }

    public static void main(String[] args) {
        //获取类上的注解
        TestAnnotation t = new TestAnnotation();
        boolean r = t.getClass().isAnnotationPresent(MyAnnotation.class);//是否应用了某个注解
        System.out.println(r);

        if(r){
            MyAnnotation a = t.getClass().getAnnotation(MyAnnotation.class);//获取Annotation对象
            System.out.println("id:" + a.id());
            System.out.println("msg:" + a.msg());
        }

        Annotation annotation[] = t.getClass().getAnnotations();    //获取所有注解
        for(Annotation an : annotation){
            System.out.println(an.annotationType());   //获取注解类型:interface com.cy.test.MyAnnotation
        }


        //获取成员变量上的注解
        Field fields[] = t.getClass().getDeclaredFields();
        Field fielda = null;
        for(Field f : fields){
            System.out.println(f.getName() +"," +f.getType() +"," + f.getGenericType() + "," + f.getModifiers());
            if(f.getName().equals("a")) fielda = f;
        }
        fielda.setAccessible(true);
        Check check = fielda.getAnnotation(Check.class);
        System.out.println("check value:"+check.value());


        //获取方法上的注解
        try {
            Method testMethod = t.getClass().getDeclaredMethod("testMethod");
            Annotation annotations[] = testMethod.getAnnotations();
            for(Annotation a : annotations) {
                System.out.println(a.annotationType().getSimpleName());
            }
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        }


    }
}

/**
 * 自定义的注解  类上
 */
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Target(ElementType.TYPE)
@interface MyAnnotation {
    int id() default 0;

    String msg() default "defaule msg";

}

/**
 * 注解  属性上
 */
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
@interface Check {
    String value();
}

/**
 * 注解  方法上
 */
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@interface Perform {

}
View Code

console:

true
id:100
msg:hello annotation
interface com.cy.test.MyAnnotation
a,int,int,2
check value:hi
Perform

@Retention

Retention 的英文意为保留期的意思。当 @Retention 应用到一个注解上的时候,它解释说明了这个注解的的存活时间。

它的取值如下: 

- RetentionPolicy.SOURCE 注解只在源码阶段保留,在编译器进行编译时它将被丢弃忽视。 
- RetentionPolicy.CLASS 注解只被保留到编译进行的时候,它并不会被加载到 JVM 中。 
- RetentionPolicy.RUNTIME 注解可以保留到程序运行的时候,它会被加载进入到 JVM 中,所以在程序运行时可以获取到它们。

我们可以这样的方式来加深理解,@Retention 去给一张标签解释的时候,它指定了这张标签张贴的时间。@Retention 相当于给一张标签上面盖了一张时间戳,时间戳指明了标签张贴的时间周期。

@Target

你可以这样理解,当一个注解被 @Target 注解时,这个注解就被限定了运用的场景。

类比到标签,原本标签是你想张贴到哪个地方就到哪个地方,但是因为 @Target 的存在,它张贴的地方就非常具体了,比如只能张贴到方法上、类上、方法参数上等等。@Target 有下面的取值

  • ElementType.ANNOTATION_TYPE 可以给一个注解进行注解

  • ElementType.CONSTRUCTOR 可以给构造方法进行注解

  • ElementType.FIELD 可以给属性进行注解

  • ElementType.LOCAL_VARIABLE 可以给局部变量进行注解

  • ElementType.METHOD 可以给方法进行注解

  • ElementType.PACKAGE 可以给一个包进行注解

  • ElementType.PARAMETER 可以给一个方法内的参数进行注解

  • ElementType.TYPE 可以给一个类型进行注解,比如类、接口、枚举

另外,上面例子代码中f.getModifiers()得到的是2,为什么?

JAVA 反射机制中,Field的getModifiers()方法返回int类型值表示该字段的修饰符。

其中,该修饰符是java.lang.reflect.Modifier的静态属性。

对应表如下:

PUBLIC: 1
PRIVATE: 2
PROTECTED: 4
STATIC: 8
FINAL: 16
SYNCHRONIZED: 32
VOLATILE: 64
TRANSIENT: 128
NATIVE: 256
INTERFACE: 512
ABSTRACT: 1024
STRICT: 2048

原文地址:https://www.cnblogs.com/tenWood/p/9497958.html