Java中提供了Annotaion(注释)功能,该功能可用于类、构造方法、成员变量、方法、参数等的声明中。该功能并不影响程序的运行,但是会对编译器警告等辅助工具产生影响。

1、定义Annotation类型

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

public @interface NoMemberAnnotation{
}

下面定义一个包含一个成员的Annotation类型。

public @interface OneMemberAnnotation{String value();
}

String:成员类型。

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

下面定义一个包含多个成员的Annotation类型。

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

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

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

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

枚举类ElementType中的枚举常量:

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

通过Annotation类型@Retention可以设置Annotation类型的有效范围。枚举类RetentionPolicy中的枚举常量用来设置@Retention。如果未设置@Retention,Annotation的有效范围为枚举常量CLASS表示的范围。

枚举类RetentionPolicy中的枚举常量:

枚举常量 说明
SOURCE 表示不编译Annotation类型到类文件中,有效范围最小
CLASS 表示编译Annotation到类文件中,但是在运行时不加载Annotation到JVM中
RUNTIME 表示在运行时加载Annotation到JVM中,有效范围最大

示例:定义并使用Annotation类型。

首先定义一个用来注释构造方法的Annotation类型@Constructor_Annotation,有效范围为在运行时加载Annotation到JVM中。

import java.lang.annotation.*;//用于构成方法
@Target(ElementType.CONSTRUCTOR)//在运行时加载Annotation到JVM
@Retention(RetentionPolicy.RUNTIME)public @interface Constructor_Annotation
{// 定义一个具有默认值的String型成员String value() default "默认构造方法";
}

然后定义一个用来注释字段、方法和参数的Annotation类型@Field_Method_Parameter_Annotation,有效范围为在运行时加载Annotation到JVM中。

import java.lang.annotation.*;//用于字段、方法和参数
@Target({ ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER })//在运行时加载Annotation到JVM中
@Retention(RetentionPolicy.RUNTIME)public @interface Field_Method_Parameter_Annotation
{String describe(); // 定义一个没有默认值的String类型成员Class type() default void.class; // 定义一个具有默认值的Class类型的成员
}

最后编写一个Record类,在该类中运行前面定义的Annotation类型对构造方法、字段、方法和参数进行注释。

/*** Record类在该类中运行前面定义的Annotation类型对构造方法、字段、方法和参数进行注释* * @author pan_junbiao**/
public class Record
{// 注释字段@Field_Method_Parameter_Annotation(describe = "编号", type = int.class)int id;@Field_Method_Parameter_Annotation(describe = "姓名", type = String.class)String name;// 采用默认值注释构造方法@Constructor_Annotation()public Record(){}// 注释构造方法@Constructor_Annotation("立即初始化构造方法")public Record(@Field_Method_Parameter_Annotation(describe = "编号", type = int.class) int id,@Field_Method_Parameter_Annotation(describe = "姓名", type = String.class) String name){this.id = id;this.name = name;}// 注释方法@Field_Method_Parameter_Annotation(describe = "获取编号", type = int.class)public int getId(){return id;}@Field_Method_Parameter_Annotation(describe = "设置编号", type = int.class)public void setId(@Field_Method_Parameter_Annotation(describe = "编号", type = int.class) int id){this.id = id;}@Field_Method_Parameter_Annotation(describe = "获取姓名", type = String.class)public int getName(){return id;}@Field_Method_Parameter_Annotation(describe = "设置姓名", type = String.class)public void setName(@Field_Method_Parameter_Annotation(describe = "姓名", type = String.class) String name){this.name = name;}
}

2、访问Annotation信息

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

类Constructor、Field和Method均继承了AccessibleObject类,在AccessibleObject中定义了3个关于Annotation的方法,其中方法isAnnotationPresent(Class<? extends Annotation> annotationClass)用来查看是否添加了指定类型的Annotation,如果是则返回true,否则返回false;方法getAnnotation(Class<T> annotationClass)用来获得指定类型的Annotation,如果存在则返回相应的对象,否则返回null;方法getAnnotations()用来获得所有的Annotation,该方法将返回一个Annotation数组。

在类Constructor和Method中还定义了方法getParameterAnnotations(),用来获得为所有参数添加的Annotation,将以Annotation类型的二维数组返回,在数组中的顺序与声明的顺序相同,如果没有参数则返回一个长度为0的数组;如果存在未添加Annotation的参数,将用一个长度为0的嵌套数组占位。

示例:访问Annotation信息。

import java.lang.annotation.Annotation;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;/*** 访问Annotation信息* * @author pan_junbiao**/
public class AnnotationTest
{public static void main(String[] args){Class recordC = null;try{recordC = Class.forName("com.helloJava.reflect.Record");} catch (ClassNotFoundException e){e.printStackTrace();}System.out.println("------ 构造方法的描述如下 ------");Constructor[] declaredConstructors = recordC.getDeclaredConstructors(); // 获得所有构造方法for (int i = 0; i < declaredConstructors.length; i++){Constructor constructor = declaredConstructors[i]; // 遍历构造方法// 查看是否具有指定类型的注释if (constructor.isAnnotationPresent(Constructor_Annotation.class)){// 获得指定类型的注释Constructor_Annotation ca = (Constructor_Annotation) constructor.getAnnotation(Constructor_Annotation.class);System.out.println(ca.value()); // 获得注释信息}Annotation[][] parameterAnnotations = constructor.getParameterAnnotations(); // 获得参数的注释for (int j = 0; j < parameterAnnotations.length; j++){// 获得指定参数注释的长度int length = parameterAnnotations[j].length;if (length == 0) // 如果长度为0则表示没有为该参数添加注释System.out.println("    未添加Annotation的参数");elsefor (int k = 0; k < length; k++){// 获得参数的注释Field_Method_Parameter_Annotation pa = (Field_Method_Parameter_Annotation) parameterAnnotations[j][k];System.out.print("    " + pa.describe()); // 获得参数描述System.out.println("    " + pa.type()); // 获得参数类型}}System.out.println();}System.out.println();System.out.println("-------- 字段的描述如下 --------");Field[] declaredFields = recordC.getDeclaredFields(); // 获得所有字段for (int i = 0; i < declaredFields.length; i++){Field field = declaredFields[i]; // 遍历字段// 查看是否具有指定类型的注释if (field.isAnnotationPresent(Field_Method_Parameter_Annotation.class)){// 获得指定类型的注释Field_Method_Parameter_Annotation fa = field.getAnnotation(Field_Method_Parameter_Annotation.class);System.out.print("    " + fa.describe()); // 获得字段的描述System.out.println("    " + fa.type()); // 获得字段的类型}}System.out.println();System.out.println("-------- 方法的描述如下 --------");Method[] methods = recordC.getDeclaredMethods(); // 获得所有方法for (int i = 0; i < methods.length; i++){Method method = methods[i]; // 遍历方法// 查看是否具有指定类型的注释if (method.isAnnotationPresent(Field_Method_Parameter_Annotation.class)){// 获得指定类型的注释Field_Method_Parameter_Annotation ma = method.getAnnotation(Field_Method_Parameter_Annotation.class);System.out.println(ma.describe()); // 获得方法的描述System.out.println(ma.type()); // 获得方法的返回值类型}Annotation[][] parameterAnnotations = method.getParameterAnnotations(); // 获得参数的注释for (int j = 0; j < parameterAnnotations.length; j++){int length = parameterAnnotations[j].length; // 获得指定参数注释的长度if (length == 0) // 如果长度为0表示没有为该参数添加注释System.out.println("    未添加Annotation的参数");elsefor (int k = 0; k < length; k++){// 获得指定类型的注释Field_Method_Parameter_Annotation pa = (Field_Method_Parameter_Annotation) parameterAnnotations[j][k];System.out.print("    " + pa.describe()); // 获得参数的描述System.out.println("    " + pa.type()); // 获得参数的类型}}System.out.println();}}
}

执行结果:

最后分享一篇很好的学习资料:Java基础加强总结(一)——注解(Annotation)

Java反射:使用Annotation功能相关推荐

  1. java反射获取注解id,通过反射获取注解(Annotation)

    以下实例,定义一个注解.通过反射获取. 主要功能:为所注解过的参数和方法附加一些信息可以获取. 定义注解. import java.lang.annotation.*; @Retention(Rete ...

  2. 月黑雁飞高,反射全知道——剖析java反射机制

    文章目录 java 反射机制 反射机制概念 java反射提供的功能 反射的基本使用 反射使用步骤(获取Class对象.调用对象方法) 反射使用 例子People 获取Class的三种方法(获取一个类的 ...

  3. 反射机制、反射机制的作用、反射机制的功能

    文章目录 一.反射机制的作用 二.Java反射机制的功能 三.反射机制相关的重要的类有哪些? 一.反射机制的作用 通过java语言中的反射机制可以i操作字节码文件(读和修改字节码文件) 通过反射机制可 ...

  4. Java反射基础,代码示例

    文章出处:https://blog.csdn.net/ylyang12/article/details/53469957 说明:本文,在转载时,对内容略作修改,更方便阅读,代码做了调试和格式整理,总之 ...

  5. java获取method,2.5 反射——Class对象功能_获取Method

    >[info] 反射--Class对象功能_获取Method * Method:方法对象 * 执行方法: * Object invoke(Object obj, Object... args) ...

  6. 使用Java反射(Reflect)、自定义注解(Customer Annotation)生成简单SQL语句

    使用Java反射(Reflect).自定义注解(Customer Annotation)生成简单SQL语句 这次给大家介绍一下在Java开发过程中 使用自定义注解开发: 主要知识点:          ...

  7. java基础-java反射机制

    2019独角兽企业重金招聘Python工程师标准>>> 引述要学习Spring框架的技术内幕,必须事先掌握一些基本的Java知识,正所谓"登高必自卑,涉远必自迩" ...

  8. java 反射 orm_Java-反射机制简介

    什么是Java反射机制? Java反射说的是在运行状态中,对于任何一个类,我们都能够知道这个类有哪些方法和属性.对于任何一个对象,我们都能够对它的方法和属性进行调用.我们把这种动态获取对象信息和调用对 ...

  9. Java反射,从0开始

    目录 静态VS动态语言 Java Reflection(反射)介绍 Java反射机制提供的功能 Java反射优点和缺点 反射相关的主要API 获取运行时类的完整结构 反射的使用 有了Class对象,如 ...

  10. java的annotation_Java Annotation认知(包括框架图、详细介绍、示例说明)

    摘要 Java Annotation是JDK5.0引入的一种注释机制. 网上很多关于Java Annotation的文章,看得人眼花缭乱.Java Annotation本来很简单的,结果说的人没说清楚 ...

最新文章

  1. Java 基础 之 关系运算符
  2. hdu 1593(数学)
  3. opencv 测试安装完成_opencv4.3 的安装(linux)
  4. linux 测试网络延迟
  5. “我的开源项目被大厂‘盗用’了!”
  6. Python中的stringIO模块
  7. 由于应用程序配置不正确
  8. 安装Ubuntu18
  9. 数控编程球面计算机,Mastercam9.1的数控编程
  10. 基于java人脸识别考勤签到系统设计与实现毕业设计毕设作品
  11. RRRR_wys' Blog 3.0 准备上线啦!
  12. jtopo node.text换行_jTopo学习笔记1
  13. 网络诊断显示“DNS服务器可能不可用”
  14. centos7无法上网问题
  15. 英语思维导图大全 连词(六)
  16. 齐次坐标(Homogeneous coordinates)
  17. 【codevs 1332】上白泽慧音
  18. php unix时间戳,php UNIX时间戳用法详解
  19. CRM哪家好?这5个CRM管理系统很好用!
  20. 深度学习CV领域必读论文

热门文章

  1. VUE 图片放大特效
  2. openwrt 修改路由ttl值
  3. 趣味三角——第8章——高斯的一个求和法
  4. 金山学院信息与机电工程系实验报告实验2 程序流程控制
  5. 赋值指令EQU与DATA
  6. 转载:关于社会保险和四金
  7. Linux之0基础入门,部署JavaWeb项目到阿里云服务器上,阿里云服务器安装MySQL并使用WorkBench连接,WorkBench导入SQL脚本,Linux之SSH和SFTP连接工具,
  8. 利用ISO文件安装CentOS8
  9. JS播放音频 JS播放mp3 JS播放音乐 Java播放音频 Java播放音乐 Java播放mp3 的jmp123.jar包安装 语音播报 Java获取根路径
  10. com.qihoo.android.float window,com.qihoo.permmgr_4.apk