当前位置: 首页 > 编程日记 > 正文

[03] 处理注解:反射


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

相关文章:

P2261 [CQOI2007]余数求和

我是题面 题意还是很清晰&#xff0c;很容易理解 1e9范围明显不能暴力&#xff0c;除非你能把常数优化到\(\frac1 {10}\)&#xff0c;但我实在想象不到用了这么多取模怎么把常数优化下去 我们可以把\(k\%i\)变成\(k-k/i*i\)(整除) 那么总的和也就从\(\sum_{i1}^{n}k\%i\)变成了…

Windows Server 2008正式版[微软官方下载地址+官方语言包]

Windows Server 2008(包含 Standard Enterprise Datacenter)32http://download.microsoft.com/download/d/d/b/ddb17dc1-a879-44dd-bd11-c0991d292ad7/6001.18000.080118-1840_x86fre_Server_en-us-KRMSFRE_EN_DVD.iso64http://download.microsoft.com/download/d/d/b/ddb17dc1…

线性代数-矩阵-【5】矩阵化简 C和C++实现

点击这里可以跳转至 【1】矩阵汇总&#xff1a;http://www.cnblogs.com/HongYi-Liang/p/7287369.html 【2】矩阵生成&#xff1a;http://www.cnblogs.com/HongYi-Liang/p/7275278.html 【3】矩阵加减&#xff1a;http://www.cnblogs.com/HongYi-Liang/p/7287403.html 【4】矩阵…

哈佛管理论丛:谁背上了令人讨厌的猴子

先说说我的读后感想&#xff1a; 在团队管理中&#xff0c;应该尽量明晰的界定每一位团队成员在当前的任务中充当的角色和应该负责的职责。 实际的执行方法就是&#xff1a;约定好给猴子喂食的时间&#xff0c;并且确定在喂食时间到来时&#xff0c;猴子应该长成什么样子。 所以…

json_encode 中文不乱码

echo json_encode("中文", JSON_UNESCAPED_UNICODE);//"中文" 转载于:https://www.cnblogs.com/zxqblogrecord/p/10300244.html

Android-room的学习

目录 关于ROOM 1.Room有3个主要的组件 2.Room 不同组件之间的关系如图所示 3.导入ROOM&#xff08;使用 Room 需要添加依赖&#xff09; 4.&#xff08;实现数据库操作的步骤&#xff09;以下代码段包含具有一个实体和一个 DAO 的示例数据库配置 实例demo 1.Student.java …

JDK5中的控制台输入

Scanner类是JDK5新添加的一个类&#xff0c;主要作用是处理输入流、文件和文本内容等 。这个类在java.util包里面&#xff0c;实现了Iterator接口&#xff0c;而且io处理采用了jdk1.4才发布的nio。由于这个类实现了Iterator接口&#xff0c;如果全部是string的话&#xff0c;就…

[BZOJ3779]重组病毒(LCT+DFS序线段树)

同[BZOJ4817]树点涂色&#xff0c;只是多了换根操作&#xff0c;分类讨论下即可。 1 #include<cstdio>2 #include<algorithm>3 #define lc ch[x][0]4 #define rc ch[x][1]5 #define ls (x<<1)6 #define rs (ls|1)7 #define lson ls,L,mid8 #define rson rs,m…

UVA - 1594 Ducci Sequence

/*做这题时的心路历程其实挺有趣的一开始看到说Ducci序列最终要么全0&#xff0c;要么循环&#xff0c;我在想&#xff1a;要怎么判断循环呢&#xff1f;是不是还得记录下循环节什么的&#xff1f;是该用数组记录循环节吗&#xff1f;还是想要让我们利用STL来记录&#xff1f;后…

RTF密码破解

有一个RTF文件带密码&#xff0c;用文本编辑器察看&#xff0c;有类似“password”字样。为了编辑它&#xff0c;有两个方法&#xff1a; 1、用word2000打开该文件&#xff0c;Tools--〉Unprotect Document&#xff0c;执行后&#xff0c;文件就可以正常编辑了。如果有多个文件…

Android 数据存储-内外部存储测试

案例分析&#xff1a;FilePersistenceTest 在EditText中输入文本内容&#xff0c;退出应用程序或者 单击“保存”按钮时 保存EditText中的数据到名 为“data”的文件中。 打开Device File Explorer&#xff0c;该文件应该存于 /data/data/cn.edu.hunnu.filepersistencetest/…

微软以后要是也开源也免费,java还竞争过.NET吗?

上次参加招聘会&#xff0c;看得到好多大公司都要求精通java&#xff0c;可惜上大学大一就学了.NET,而java到大三才开&#xff0c;并且草草地只讲了些基本知识。有时我就在想难道学当初选择.NET真的错了吗&#xff1f;java确实比.NET存在很多优势。开源、跨平台、免费、开发工具…

Android Studio开发环境及第一个项目

1. 在你的电脑上搭建Android平台开发环境。 2. 新建项目&#xff0c;实现以下基本内容&#xff1a; (1) 修改默认的APP的名称和图标&#xff08;任意的&#xff0c;非默认的&#xff09;。 (2) 显示个人信息&#xff0c;包括&#xff1a;照片、专业、姓名、学号等基本信息。…

去除inline-block元素间距

转载于:https://www.cnblogs.com/keepitreal/p/10301199.html

C#ListView控件添加Checkbox复选框并获取选中的数目,检查checkbox是否勾选

[转载]原地址&#xff1a;http://blog.csdn.net/lucky51222/article/details/41892429 具体方法 1、添加复选框 并且如下设置 listView1.CheckBoxes true; 2、选中listview并获取选中的数目&#xff1a; 具体代码 private void listView1_ItemChecked(object sender, ItemChec…

weblogic学习笔记(1)

weblogic安装、配置和启动 1、weblogic安装转载于:https://blog.51cto.com/pengchenga/66424

react 从使用 看定义

如果你创建了一个类似元素做出反应Twitter的下面&#xff0c;你会的组件定义Twitter的样子&#xff1f; <Twitter usernametylermcginnis33>{(user) > user null? <Loading />: <Badge info{user} />} </Twitter> import React, { Component, Pro…

Android 活动与活动间数据传递

实验内容 综合运用基本组件完成一个注册与登录的应用程序设计。要求基于基础控件&#xff0c;综合使用Intent实现Android的Activity之间信息交换。系统包含启动页、注册页、登录页3个页面&#xff0c;具体要求如下&#xff1a; 1.注册页面和功能的实现。 –界面要求包含用户…

Selenium-js弹窗浮层

学习过js的小伙伴会发现&#xff0c;我们在一些实例中用到了alert()方法、prompt()方法、prompt()方法&#xff0c;他们都是在屏幕上弹出一个对话框&#xff0c;并且在上面显示括号内的内容&#xff0c;使用这种方法使得页面的交互性更精彩&#xff0c;实际上我们经常会在进行网…

JAVA基础(JAVA 执行环境) 第一天

JAVA程序有3中执行环境。 &#xff08;1&#xff09;能够单独运行的程序&#xff0c;称为Java Application(Java应用程序)。 &#xff08;2&#xff09;在Internet浏览器中运行的程序&#xff0c;称为 Java Applet&#xff08;JAVA小用用程序&#xff09;。Applet是一个在WEB浏…

ERP图形目录

这些天正在研究ERP&#xff0c;老师要求我们自己制作一个ERP出来。找了不少资料&#xff0c;就这个图形目录比较有学习价值。这个图形目录是PDF文件&#xff0c;包括销售管理、采购管理、库存管理、制作标准管理、计划管理、车间管理、JIT生产管理、质量管理、财务管理、人力资…

JSP学习笔记(五):日期处理、页面重定向、点击量统计、自动刷新和发送邮件...

一、JSP 日期处理&#xff1a; 使用JSP最重要的优势之一&#xff0c;就是可以使用所有Java API。本节讲述Java中的Date类&#xff0c;它在java.util包下&#xff0c;封装了当前日期和时间。 Date类有两个构造函数。第一个构造函数使用当前日期和时间来初始化对象&#xff1a;D…

完善登录注册页面

实验内容 综合运用基本组件完成一个注册与登录的应用程序设计。要求基于基础控件&#xff0c;综合使用Intent实现Android的Activity之间信息交换。系统包含启动页、注册页、登录页3个页面&#xff0c;具体要求如下&#xff1a; 在第2周上机作业的基础上&#xff0c;完善登录注…

EF 批量 添加 修改 删除

1批量添加 db.T_Investigator.AddRange(list) 2批量删除 db.T_Investigator.RemoveRange(list) 3批量修改 for 循环修改。 注意&#xff1a; 先查询出来&#xff0c;最后savechange&#xff08;&#xff09;&#xff0c;写在一个事务中&#xff0c;一次请求一个上下文。…

在IE7中无效的解决办法

通过ShowModalDialog 打开页面,在POSTBACK时,打开新的页面&#xff0c; 在IE6下没问题,只有在IE7下,会重新打开一新页面&#xff0c; 其实只要把<base target"_self"/> 放到 <head>下即可。 <head> <base target"_self"/> …

简单的纹理管理器

简单的纹理管理器 罗朝辉 (http://www.cnblogs.com/kesalin/)本文遵循“署名-非商业用途-保持一致”创作公用协议游戏中的资源一般都是由资源管理器来处理的&#xff0c;资源管理器负责载入&#xff0c;释放&#xff0c;以及根据资源ID返回相关资源供游戏程序使用。下面改写sph…

记住密码以及Android 列表的操作

1.综合使用RecycleView&#xff0c;CardView&#xff0c;Adapter实现一个宝宝相册&#xff0c;并将其加入到实验一形成的应用中&#xff0c;使得&#xff1a;用户成功登录后转到宝宝相册所在的主界面。还要求实现&#xff1a;用户单击对应的列表子项的不同部位时给出不同的Toas…

python-----利用filecmp删除重复文件

以下代码素材自取&#xff1a;链接&#xff1a;https://pan.baidu.com/s/1fL17RjKyGjpvpeeUFONCaQ 提取码&#xff1a;zgiw # coding:utf-8 import os import filecmp# 将指定目录下的所有文件的路径存储到all_files变量中 def get_all_files(path, dirs):all_files []for d …

如何设置REUSE_ALV_GRID_DISPLAY'的单个单元格的是否可以输入

代码如下&#xff1a;具体说明参见红色说明(本例子是从订单明细提取两个字段的数据到内表) REPORT ZALV_EDIT.TYPE-POOLS: SLIS.*- FieldcatalogDATA: IT_FIELDCAT TYPE LVC_T_FCAT.DATA: X_FIELDCAT TYPE LVC_S_FCAT.DATA: X_LAYOUT TYPE LVC_S_LAYO. "第1步&#xff1a;…

记一次生产的bug

第一个在代码中使用 new SimpleDateFormat("EEEE")来判断周几。在本地测试过程中通过日志打印出来的周几 比如周日对应的是中文汉字“星期日”&#xff0c;然后使用判断 if("星期日".equals(weekDay)){ } (其中weekDay是要使用的日期)。在本地测试通过后…