JDK1.5开始增加了Annotation功能,该功能可用于:

1、类;

2、构造方法;

3、成员变量;

4、方法

5、参数

等的声明;

该功能并不影响程序的运行,但是会对编译器警告等辅助工具产生影响。本文将介绍Annotation功能的使用方法。


1、定义Annotation类型

在定义Annotation类型时,也需要用到来定义接口的interface关键字,但需要在interface关键字前加一个@符号,即表示定义Annotation类型的关键字为@interface,这个关键字的隐含意思是继承了java.lang.annotation.Annotation接口。例如,下面的代码就定义了一个Annotation类型。

public @interface NoMemberAnnotation{}

上面定义的Annotation类型@NoMemberAnnotation未包含任何成员,这样的Annotation类型被称为marker annotation。下面的代码定义了一个只包含一个成员的Annotation类型。

public @interface OneMemberAnnotatino{
String value();
}

String: 成员类型。可用的成员类型有:

1)String;

2)Class;

3)基本类型;

4)枚举;

5)Annotation;

value:成员的名称。如果在所定义的Annotation类型中只包含一个成员,通常将成员命名为value;

下面代码定义了一个包含多个成员的Annotation类型:

public @interface MoreMemberAnnotation{
String describe();
Class type();
}

在为Annotation类型定义成员时,也可以为成员设置默认值。例如,下面的代码在定义Annotation类型时就为成员设置了默认值。

public @interface DefaultValueAnnotation{
String describe() default "<默认值>";
Class type(0 default void.class;
}

在定义Annotation类型时,还可以通过Annotation类型@Target来设置Annotation类型使用的程序元素种类。如果未设置@Target,则表示适用于所有程序元素。枚举类ElementType中的枚举常量用来设置@Target,如下:

  • ANNOTATION_TYPE :表示用于Annotation类型
  • TYPE : 表示用于类、接口和枚举,以及Annotation类型
  • CONSTRUCTOR : 表示用于构造方法
  • FIELD : 表示用于成员变量和枚举常量
  • METHOD :表示用于方法
  • PARAMETER :表示用于参数
  • LOCAL_VARIABLE :表示用于局部变量
  • PACKAGE :表示用于包

通过Annotation类型的@Retention可以设置Annotation的有效范围。枚举类RetentionPolicy中的枚举常量用于设置@Retention,如果没有设置,那么默认为CLASS常量的范围,如下所示:

  • SOURCE :表示不编译Annotation到类文件中,有效范围最小
  • CLASS :表示编译Annotation到类文件中,但是在运行时不加载Annotation到JVM中
  • RUNTIME :表示在运行时加载Annotation到JVM中,有效范围最大

2、访问Annotation信息

如果在定义Annotation类型时将@Retention设置为RetetionPolicy.RUNTIME,那么在运行程序时通过反射就可以获取到相关的Annotation信息,如获取构造方法、字段和方法的Annotation信息。

类Constructor、Field和Method继承了AccessibleObject类,而AccessibleObject类实现了AnnotatedElement,因此也就是说,Constructor、FIeld、Method均可以使用AccessibleObject实现的方法来操作注解。(注:这里Class类直接实现了AnnotatedElement不是继承AccessibleObject)

下面,我们看看AccessibleObject继承来的方法:

<T extends Annotation> getAnnotation(Class<T> annotationClass);

如果该元素存在annotationClass类型的注释,则返回该注释,否则返回null;

Annotation[] getAnnotations()

返回该元素的所有注解

Annotation[] getDeclaredAnnotation()

返回直接存在于该元素的注解(例如继承而来的注解不会被返回)

boolean isAccessible()

该元素是否执行安全检查(安全检查如:变量设置了private属性不可以直接访问,设置为取消检查则可以反问该元素)

boolean isAnnotationPresent(Class<? extends Annotation> annotationClass)

该元素是否存在annotationClass注解

static void setAccessible(AccessibleObject[] array, boolean flag)

为一组元素设置是否执行安全检查

void setAccessible(boolean flag)

为该元素设置是否执行安全检查


3、DEMO

package cn.lay.annotation;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target; /**
* annotation demo
* @ClassName: AnnotationDemo
* @Description:
* @author: lay
* @date: Mar 18, 2018
*/
@Test(
value = "test",
ages = {23, 23, 34, 35, 34},
bookEnum = BookEnum.JAVA,
cls = String.class,
test2s = {@Test2(), @Test2("lay"), @Test2("zhang"), @Test2("wu")}
)
public class AnnotationDemo {
public static void main(String[] args) {
// 判断是否注解了该类型
if (AnnotationDemo.class.isAnnotationPresent(Test.class)) {
// 获取该注解
Test annotation = AnnotationDemo.class.getAnnotation(Test.class);
// 取值
String value = annotation.value();
// 输出
System.out.println("value=" + value);
int[] ages = annotation.ages();
for (int age : ages) {
System.out.println("age=" + age);
}
BookEnum bookEnum = annotation.bookEnum();
System.out.println("bookName=" + bookEnum.getBookName());;
Class<?> cls = annotation.cls();
System.out.println("class=" + cls.getName());
Test2[] test2s = annotation.test2s();
for (Test2 test2 : test2s) {
System.out.println("test2=" + test2.value());
}
}
}
} /**
* 定义注解
* @ClassName: Test
* @Description:
* @author: lay
* @date: Mar 18, 2018
*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@interface Test{
String value();
int[] ages();
BookEnum bookEnum();
Class<?> cls();
Test2[] test2s();
} @Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@interface Test2{
String value() default "lily";
} enum BookEnum{ JAVA("java"),
SQL("sql"); private String bookName; public String getBookName() {
return bookName;
} public void setBookName(String bookName) {
this.bookName = bookName;
} private BookEnum(String bookName) {
this.bookName = bookName;
}
}

控制台打印:

value=test
age=23
age=23
age=34
age=35
age=34
bookName=java
class=java.lang.String
test2=lily
test2=lay
test2=zhang
test2=wu

更多详细内容,参阅:http://tool.oschina.net/apidocs/apidoc?api=jdk-zh

Java API 之 Annotation功能的更多相关文章

  1. ElasticSearch7.3学习(三十)----ES7.X SQL新特性解析及使用Java api实现sql功能

    一.ES7 sql新特性 1.1 数据准备 创建索引及映射 建立价格.颜色.品牌.售卖日期 四个字段 PUT /tvs PUT /tvs/_mapping { "properties&quo ...

  2. 第08章 ElasticSearch Java API

    本章内容 使用客户端对象(client object)连接到本地或远程ElasticSearch集群. 逐条或批量索引文档. 更新文档内容. 使用各种ElasticSearch支持的查询方式. 处理E ...

  3. 【转】Java奇技淫巧-插件化注解处理API(Pluggable Annotation Processing API)

    参考资料 JDK6的新特性之六:插入式注解处理API(Pluggable Annotation Processing API) Java Annotation Processing and Creat ...

  4. 常用Java API之Scanner:功能与使用方法

    Scanner 常用Java API之Scanner:功能与使用方法 Scanner类的功能:可以实现键盘输入数据到程序当中. 引用类型的一般使用步骤:(Scanner是引用类型的) 1.导包 imp ...

  5. API 注解 & Java API annotation

    API 注解 & Java API annotation 注解 annotation

  6. Java基础笔记 – Annotation注解的介绍和使用 自定义注解

    Java基础笔记 – Annotation注解的介绍和使用 自定义注解 本文由arthinking发表于5年前 | Java基础 | 评论数 7 |  被围观 25,969 views+ 1.Anno ...

  7. RabbitMQ的Java API编程

    1.创建Maven工程,pom.xml引入依赖: <dependency> <groupId>com.rabbitmq</groupId> <artifact ...

  8. Java API 各个包的内容解释

    java.applet 提供创建 applet 所必需的类和 applet 用来与其 applet 上下文通信的类. java.awt 包含用于创建用户界面和绘制图形图像的所有类. java.awt. ...

  9. 插件化注解处理API(Pluggable Annotation Processing API)

    Java奇技淫巧-插件化注解处理API(Pluggable Annotation Processing API) 参考资料 JDK6的新特性之六:插入式注解处理API(Pluggable Annota ...

随机推荐

  1. 求解任意图的最小支配集(Minimun Dominating Set)

    给定一个无向图G =(V,E),其中V表示图中顶点集合,E表示边的集合.G的最小控制顶点集合为V的一个子集S∈V:假设集合R表示V排除集合S后剩余顶点集合,即R∩S=∅,R∪S=V:则最小控制顶点集合 ...

  2. vue.js 一些知识点

    vue.js 也是试图层的运用方法,跟react的方法类似,不过也有许多的不同地方: 1.vue.js 对于数据也是用{{ }} 进行数据更新: 2.vue.js 使用 v-html 指令用于输出 h ...

  3. 洛谷P2495 [SDOI2011]消耗战(虚树)

    题面 传送门 题解 为啥一直莫名其妙\(90\)分啊--重构了一下代码才\(A\)掉-- 先考虑直接\(dp\)怎么做 树形\(dp\)的时候,记一下断开某个节点的最小值,就是从根节点到它的路径上最短 ...

  4. uC/OS-II 函数之消息队列相关函数

    上文主要介绍了信号量相关的函数,本文介绍消息队列相关的函数:OSQCreate()建立消息队列函数,OSQPend()任务等待消息函数,其他的消息函数. 消息队列介绍 消息队列是µC/OS-II中另一 ...

  5. scrollto 到指定位置

    goTo = function(target){ var scrollT = document.body.scrollTop|| document.documentElement.scrollTop ...

  6. 977 AlvinZH过生日(背包DP大作战S)

    977 AlvinZH过生日 思路 难题.逆推DP. 要明确dp的状态只与是否有选择权有关,而与选择权在谁手里无关.因为不论选择权在谁手里,那个人都会尽可能的获得最大的蛋糕重量. dp[i]表示分配到 ...

  7. 自定义View实现钟摆效果进度条PendulumView

    转载请注明出处:http://blog.csdn.net/fightlei/article/details/52556755 在网上看到了一个IOS组件PendulumView,实现了钟摆的动画效果. ...

  8. 大数据-spark HA集群搭建

    一.安装scala 我们安装的是scala-2.11.8  5台机器全部安装 下载需要的安装包,放到特定的目录下/opt/workspace/并进行解压 1.解压缩 [root@master1 ~]# ...

  9. pip安装python库总是超时或出错的解决办法

    建个文件 ~/.pip/pip.conf, 内容如下 [global] timeout = index-url = http://pypi.douban.com/simple/ [install] u ...

  10. 2018牛客多校1 - J Different Integers 莫队/主席树签到

    题意:给出n<5e4,a[1...n],单次1e5总次1e6次查询除去区间(L,R)的数的个数 开场5分钟:莫队是不可能莫队的,这道题是不可能莫队的 最后1小时:真香 具体操作没啥特别的,注意一 ...