参考博客:
感觉这篇文章写得非常好,讲的很清楚明白,易于理解;例子也很不错,做个记录:
代码:
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:
trueid:100msg:hello annotationinterface com.cy.test.MyAnnotationa,int,int,2check value:hiPerform
@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: 2PROTECTED: 4STATIC: 8FINAL: 16SYNCHRONIZED: 32VOLATILE: 64TRANSIENT: 128NATIVE: 256INTERFACE: 512ABSTRACT: 1024STRICT: 2048