1、AnnotatedElement接口

如果没有用来读取注解的方法和工作,那么注解也就不会比注释更有用处了。使用注解的过程中,很重要的一部分就是创建于使用注解处理器。Java SE5扩展了反射机制的API,以帮助程序员快速的构造自定义注解处理器。
Java用Annotation接口来代表程序元素前面的注解,该接口是所有Annotation类型的父接口。如在java.lang.reflect包中有一个接口AnnotatedElement,其中定义了一些注解相关的方法,如判断某元素是否标注了注解的方法:
  • boolean isAnnotationPresent(Class<? extends Annotation> annotationClass)
  • 这里的传参实际上就是传入 ”某个注解.class“
另外,Java在java.lang.reflect 包下新增了 AnnotatedElement 接口:
/** * Represents an annotated element of the program currently running in this* VM.  This interface allows annotations to be read reflectively.  All* annotations returned by methods in this interface are immutable and* serializable.  It is permissible for the caller to modify the* arrays returned by accessors for array-valued enum members; it will* have no affect on the arrays returned to other callers.** <p>If an annotation returned by a method in this interface contains* (directly or indirectly) a {@link Class}-valued member referring to* a class that is not accessible in this VM, attempting to read the class* by calling the relevant Class-returning method on the returned annotation* will result in a {@link TypeNotPresentException}.** <p>Similarly, attempting to read an enum-valued member will result in* a {@link EnumConstantNotPresentException} if the enum constant in the* annotation is no longer present in the enum type.* * <p>Finally, Attempting to read a member whose definition has evolved* incompatibly will result in a {@link* java.lang.annotation.AnnotationTypeMismatchException} or an* {@link java.lang.annotation.IncompleteAnnotationException}.** @since 1.5* @author Josh Bloch*/
26
1
/** 

2
 * Represents an annotated element of the program currently running in this

3
 * VM.  This interface allows annotations to be read reflectively.  All

4
 * annotations returned by methods in this interface are immutable and

5
 * serializable.  It is permissible for the caller to modify the

6
 * arrays returned by accessors for array-valued enum members; it will

7
 * have no affect on the arrays returned to other callers.

8
 *

9
 * <p>If an annotation returned by a method in this interface contains

10
 * (directly or indirectly) a {@link Class}-valued member referring to

11
 * a class that is not accessible in this VM, attempting to read the class

12
 * by calling the relevant Class-returning method on the returned annotation

13
 * will result in a {@link TypeNotPresentException}.

14
 *

15
 * <p>Similarly, attempting to read an enum-valued member will result in

16
 * a {@link EnumConstantNotPresentException} if the enum constant in the

17
 * annotation is no longer present in the enum type.

18
 * 

19
 * <p>Finally, Attempting to read a member whose definition has evolved

20
 * incompatibly will result in a {@link

21
 * java.lang.annotation.AnnotationTypeMismatchException} or an

22
 * {@link java.lang.annotation.IncompleteAnnotationException}.

23
 *

24
 * @since 1.5

25
 * @author Josh Bloch

26
 */

该接口代表程序中可以接受注解的程序元素,这句话怎么理解?我们从另一头倒着来理:
(1)Field、Method、Constructor
在反射中我们知道的像属性、方法、构造函数等封装的类,都继承了一个类,叫AccessibleObject;
(2)AccessibleObject (参考链接)
java.lang.reflect包中有类AccessibleObject,从类的注释可以看出,The AccessibleObject class is the base class for Field, Method and Constructor objects. It provides the ability to flag a reflected object as suppressing default Java language access control checks when it is used. 显然,它可以让一个反射对象去禁止Java语言的访问控制检测,从而能够调用对象的私有属性和方法。
这个类实现了一个接口,就是我们提到的AnnotatedElement了,实现该接口的类(Represents an annotated element of the program currently running in this VM.  This interface allows annotations to be read reflectively.)即代表那些可注解的元素,同时可以利用反射机制读取注解。所以,它的几个主要实现类有:
  • Class  类
  • Constructor  构造器
  • Field  类的成员变量
  • Method  类的方法
  • Package  类的包
注意:如Class、Package未继承AccessibleObject,毕竟这两个类不需要所谓的访问权限设置,但是它们是实现了AnnotatedElement接口的。
所以当我们通过反射获取某个类的AnnotatedElement对象之后,就可以调用AnnotatedElement接口定义好的几个方法:
  • //判断该程序元素上是否包含指定类型的注解,存在返回true,否则返回false
  • boolean isAnnotationPresent(Class<? extends Annotation> annotationClass);
  • //返回该程序元素上存在的、指定类型的注解,如果该类型注解不存在,则返回null
  • <T extends Annotation> T getAnnotation(Class<T> annotationClass);
  • //返回该程序元素上存在的所有注解
  • Annotation[] getAnnotations();
  • //返回直接存在于该元素上的所有注解(与该接口中其他方法不同,该方法将忽略继承的注解)
  • //如果没有注解直接存在于此元素上,则返回长度为零的一个数组
  • //该方法调用者可以随意修改返回的数组,不会对其他调用者返回的数组产生影响
  • Annotation[] getDeclaredAnnotations();

2、AnnotatedElement使用示例

2.1 自定义注解

/*** 水果名称注解*/
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface FruitName {String value() default "";
}/*** 水果颜色注解*/
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface FruitColor {/*** 颜色枚举*/public enum Color {BULE, RED, GREEN}/*** 颜色属性*/public Color fruitColor() default Color.GREEN;
}/*** 水果供应商注解*/
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface FruitProvider {/*** 供应商编号*/public int id() default -1;/*** 供应商名称*/public String name() default "";/*** 供应商地址*/public String address() default "";}
54
1
/**

2
 * 水果名称注解

3
 */

4
@Target(ElementType.FIELD)

5
@Retention(RetentionPolicy.RUNTIME)

6
@Documented

7
public @interface FruitName {

8
    String value() default "";

9
}

10
11
12
/**

13
 * 水果颜色注解

14
 */

15
@Target(ElementType.FIELD)

16
@Retention(RetentionPolicy.RUNTIME)

17
@Documented

18
public @interface FruitColor {

19
    /**

20
     * 颜色枚举

21
     */

22
    public enum Color {BULE, RED, GREEN}

23
24
    /**

25
     * 颜色属性

26
     */

27
    public Color fruitColor() default Color.GREEN;

28
}

29
30
31
/**

32
 * 水果供应商注解

33
 */

34
@Target(ElementType.FIELD)

35
@Retention(RetentionPolicy.RUNTIME)

36
@Documented

37
public @interface FruitProvider {

38
39
    /**

40
     * 供应商编号

41
     */

42
    public int id() default -1;

43
44
    /**

45
     * 供应商名称

46
     */

47
    public String name() default "";

48
49
    /**

50
     * 供应商地址

51
     */

52
    public String address() default "";

53
54
}

注意:当一个Annotation类型被定义为运行时(RUNTIME)的Annotation时,该注解才能是运行时可见,当class文件被装载时被保存在class文件中的Annotation才会被虚拟机读取。

2.2 使用自定义注解的类

/*** 苹果类*/
public class Apple {/*** 苹果名称*/@FruitName("红富士")private String appleName;/*** 苹果颜色*/@FruitColor(fruitColor = FruitColor.Color.RED)private String appleColor;/*** 苹果供应商*/@FruitProvider(id = 1, name = "陕西红富士集团", address = "陕西省西安市延安路89号红富士大厦")private String appleProvider;public String getAppleName() {return appleName;}public void setAppleName(String appleName) {this.appleName = appleName;}public String getAppleColor() {return appleColor;}public void setAppleColor(String appleColor) {this.appleColor = appleColor;}public String getAppleProvider() {return appleProvider;}public void setAppleProvider(String appleProvider) {this.appleProvider = appleProvider;}
}
47
1
/**

2
 * 苹果类

3
 */

4
public class Apple {

5
6
    /**

7
     * 苹果名称

8
     */

9
    @FruitName("红富士")

10
    private String appleName;

11
12
    /**

13
     * 苹果颜色

14
     */

15
    @FruitColor(fruitColor = FruitColor.Color.RED)

16
    private String appleColor;

17
18
    /**

19
     * 苹果供应商

20
     */

21
    @FruitProvider(id = 1, name = "陕西红富士集团", address = "陕西省西安市延安路89号红富士大厦")

22
    private String appleProvider;

23
24
    public String getAppleName() {

25
        return appleName;

26
    }

27
28
    public void setAppleName(String appleName) {

29
        this.appleName = appleName;

30
    }

31
32
    public String getAppleColor() {

33
        return appleColor;

34
    }

35
36
    public void setAppleColor(String appleColor) {

37
        this.appleColor = appleColor;

38
    }

39
40
    public String getAppleProvider() {

41
        return appleProvider;

42
    }

43
44
    public void setAppleProvider(String appleProvider) {

45
        this.appleProvider = appleProvider;

46
    }

47
}

2.3 注解处理

public class FruitInfoUtil {/*** 获取水果信息* @param clazz 类对象*/public static void getFruitInfo(Class<?> clazz) {String strFruitName;String strFruitColor;String strFruitProvider;//获取该类对象包含的所有属性对象Field[] fields = clazz.getDeclaredFields();//遍历属性对象for (Field field : fields) {//如果属性包含的注解是FruitNameif (field.isAnnotationPresent(FruitName.class)) {FruitName fruitName = field.getAnnotation(FruitName.class);strFruitName = "水果名称:" + fruitName.value();System.out.println(strFruitName);}//如果属性包含的注解是FruitColorelse if (field.isAnnotationPresent(FruitColor.class)) {FruitColor fruitColor = field.getAnnotation(FruitColor.class);strFruitColor = "水果颜色:" + fruitColor.fruitColor().toString();System.out.println(strFruitColor);}//如果属性包含的注解是FruitProviderelse if (field.isAnnotationPresent(FruitProvider.class)) {FruitProvider fruitProvider = field.getAnnotation(FruitProvider.class);strFruitProvider = "供应商编号:" + fruitProvider.id()+ ";供应商名称:" + fruitProvider.name()+ ";供应商地址:" + fruitProvider.address();System.out.println(strFruitProvider);}}}}
41
1
public class FruitInfoUtil {

2
3
    /**

4
     * 获取水果信息

5
     * @param clazz 类对象

6
     */

7
    public static void getFruitInfo(Class<?> clazz) {

8
9
        String strFruitName;

10
        String strFruitColor;

11
        String strFruitProvider;

12
13
        //获取该类对象包含的所有属性对象

14
        Field[] fields = clazz.getDeclaredFields();

15
16
        //遍历属性对象

17
        for (Field field : fields) {

18
            //如果属性包含的注解是FruitName

19
            if (field.isAnnotationPresent(FruitName.class)) {

20
                FruitName fruitName = field.getAnnotation(FruitName.class);

21
                strFruitName = "水果名称:" + fruitName.value();

22
                System.out.println(strFruitName);

23
            }

24
            //如果属性包含的注解是FruitColor

25
            else if (field.isAnnotationPresent(FruitColor.class)) {

26
                FruitColor fruitColor = field.getAnnotation(FruitColor.class);

27
                strFruitColor = "水果颜色:" + fruitColor.fruitColor().toString();

28
                System.out.println(strFruitColor);

29
            }

30
            //如果属性包含的注解是FruitProvider

31
            else if (field.isAnnotationPresent(FruitProvider.class)) {

32
                FruitProvider fruitProvider = field.getAnnotation(FruitProvider.class);

33
                strFruitProvider = "供应商编号:" + fruitProvider.id()

34
                        + ";供应商名称:" + fruitProvider.name()

35
                        + ";供应商地址:" + fruitProvider.address();

36
                System.out.println(strFruitProvider);

37
            }

38
        }

39
    }

40
    

41
}

2.4 测试和结果输出

public class TestAnnotation {public static void main(String[] args) {FruitInfoUtil.getFruitInfo(Apple.class);}
}//结果输出
水果名称:红富士
水果颜色:RED
供应商编号:1;供应商名称:陕西红富士集团;供应商地址:陕西省西安市延安路89号红富士大厦
x
1
public class TestAnnotation {

2
    public static void main(String[] args) {

3
        FruitInfoUtil.getFruitInfo(Apple.class);

4
    }

5
}

6
7
//结果输出

8
水果名称:红富士

9
水果颜色:RED

10
供应商编号:1;供应商名称:陕西红富士集团;供应商地址:陕西省西安市延安路89号红富士大厦

3、参考链接

  • 深入理解Java:注解(Annotation)--注解处理器

转载于:https://www.cnblogs.com/deng-cc/p/7462588.html

[03] 处理注解:反射相关推荐

  1. java学习~线程、注解反射、Swagger

    这几天一直在学习java基础,所以跟着老师一起学习做的总结. 项目地址:StudyJava项目地址 一:线程学习 这是代码的布局以及对各个类的描述和总结.可以借鉴. 线程代码地址:thread No1 ...

  2. Java 枚举注解反射

    4-9 枚举&注解&反射 枚举 引入的目的:用于定义有限数量的一组同类常量,限定了使用者在使用时常量的取值范围. Java中枚举的演变: java1.5前使用类+final修饰变量+私 ...

  3. 使用注解+反射实现List与树形结构的相互转换

    应用场景: 提示:此种写法只适用于数据量小的转换,数据量大时请移步另一个方案 [一次循环实现List转树形结构(不使用递归)](https://blog.csdn.net/weixin_3730496 ...

  4. 利用注解 + 反射消除重复代码(Java项目)

    作者 | Leilei Chen 来源 | https://llchen60.com/ 1. 案例场景 假设银行提供了一些 API 接口,对参数的序列化有点特殊,不使用 JSON,而是需要我们把参数依 ...

  5. Java_注解 反射 字节码 类加载机制

    一.注解  1. 二.反射  1.动态语言:python.js    程序运行时,可以改变程序结构或变量类型. java的动态性:利用反射机制.字节码操作获得类似动态语言的特性. 2.反射机制 ref ...

  6. 利用注解 + 反射消除重复代码,妙!

    1.1 案例场景 假设银行提供了一些 API 接口,对参数的序列化有点特殊,不使用 JSON,而是需要我们把参数依次拼在一起构成一个大字符串: 1)按照银行提供的API文档顺序,将所有的参数构成定长的 ...

  7. java 重复代码优化_利用注解 + 反射消除重复代码(Java项目)

    1. 案例分析 1.1 案例场景 假设银行提供了一些 API 接口,对参数的序列化有点特殊,不使用 JSON,而是需要我们把参数依次拼在一起构成一个大字符串 按照银行提供的API文档顺序,将所有的参数 ...

  8. 枚举注解反射整合详解

    一丶枚举 1 ** 2 * 一.枚举类的使用 3 * 1.枚举类的理解:类的对象只有有限个,确定的.我们称此类为枚举类 4 * 2.当需要定义一组常量时,强烈建议使用枚举类 5 * 3.如果枚举类中只 ...

  9. JAVA基础,注解反射机制

    文章目录 注解 (非常重要) 什么是注解 基本注解 @Override @Deprecated @SuppressWarnings @SafeVarargs @FunctionalInterface ...

最新文章

  1. 干掉 ZooKeeper?阿里为什么不用 ZK 做服务发现?
  2. 南安出台行动方案推进智慧城市建设
  3. 4分钟极速甩脂训练!抛开借口!繁忙族必备!
  4. 【图像分类】从数据集和经典网络开始
  5. Python操作excel文件根据某一字段将相同的类拆分
  6. php 组合模式,php设计模式(十三)透明组合模式
  7. Sublime Text 3 Mac常用快捷键与注意事项
  8. 重庆大二学生花了6年写出了操作系统
  9. Java 线程之间通信
  10. bzoj1005 [HNOI2008]明明的烦恼 prufer+组合数学
  11. 计算机无法上网修复工具,lsp怎么修复解决上不了网问题汇总
  12. 解决input输入中文时,拼音在输入框内会触发input事件的问题
  13. mysql 存储过程 对象_【MYSQL笔记3】MYSQL过程式数据库对象之存储过程的调用、删除和修改...
  14. Kotlin基础篇(二)-作用域函数
  15. 地址栏中输入IP地址提示指定的网络名不再可用的解决方法
  16. 通过有线网卡共享无线网络
  17. Docker网络及资源管理
  18. 该设备正在使用中,请关闭可能使用该设备的所有程序或窗口,然后重试
  19. 林肯公园(LINKIN PARK)上海演唱会观众座位表(转帖)
  20. 如何用海思HI3516DV300/3518EV200推流H.264

热门文章

  1. POJ 3080 多个串最长公共子序列
  2. MVC使用Flash来显示图片
  3. 公司运作 - 利润率、周转率
  4. 据说是腾讯php程序员面试题目 蛋疼..要是提供PHP手册就HI了..
  5. jupyter安装与初探
  6. zabbix简介及基本安装(一)
  7. (C++)一行代码递归实现辗转相除法
  8. java程序员入门先学什么开发者工具
  9. 【数据排序】车厢重组
  10. 配置linux-Fedora系统下iptables防火墙