参考博客: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 { }
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