Annotation(注解)就是Java提供了一种元程序中的元素关联任何信息和着任何元数据(metadata)的途径和方法。Annotion(注解)是一个接口,程序可以通过反射来获取指定程序元素的Annotion对象,然后通过Annotion对象来获取注解里面的元数据。
元注解的作用就是负责注解其他注解。Java5.0定义了4个标准的meta-annotation类型,它们被用来提供对其它annotation类型作说明。Java5.0定义的元注解:
@Documented 是否会保存到 Javadoc 文档中
@Retention 保留时间,可选值
SOURCE(源码时),CLASS(编译时),RUNTIME(运行时),默认为 CLASS,SOURCE 大都为 Mark Annotation,这类 Annotation 大都用来校验,比如 Override, SuppressWarnings
ANONOTATION_TYPE(注解类型声明), PACKAGE(包) TYPE (类,包括enum及接口,注解类型) METHOD (方法) CONSTRUCTOR (构造方法) FIFLD (成员变量) PARAMATER (参数) LOCAL_VARIABLE (局部 变量)
元数据从metadata一词译来,就是“关于数据的数据”的意思。 元数据的功能作用有很多,比如:你可能用过Javadoc的注释自动生成文档。这就是元数据功能的一种。总的来说,元数据可以用来创建文档,跟踪代码的依赖性,执行编译时格式检查,代替已有的配置文件。如果要对于元数据的作用进行分类,目前还没有明确的定义,不过我们可以根据它所起的作用,大致可分为三类:
其他知识点暂时不介绍,个人觉得一下子介绍太多概念很难消化。下面让我们一起结合例子来使用它。
自定义注解大概可分为以下三个步骤:
/* * 定义注解 MethodInfo * 为方便测试:注解目标为类 方法,属性及构造方法 * 注解中含有三个元素 id ,name和 gid; * id 元素 有默认值 0 */ @Documented @Target({ElementType.TYPE,ElementType.METHOD, ElementType.FIELD,ElementType.CONSTRUCTOR}) @Retention(RetentionPolicy.RUNTIME) @Inherited public @interface MethodInfo { String name() default "xujunTest"; int id() default 0; Class<Long> gid(); } 复制代码
(1). 通过 @interface 定义,注解名即为自定义注解名,这里注解名为MethodInfo
(2). 注解配置参数名为注解类的方法名,且:
a. 所有方法没有方法体,没有参数没有修饰符,实际只允许 public & abstract 修饰符,默认为 public,不允许抛异常
b. 方法返回值只能是基本类型,String, Class, annotation, enumeration 或者是他们的一维数组
c. 若只有一个默认属性,可直接用 value() 函数。一个属性都没有表示该 Annotation 为 Mark Annotation
(3). 可以加 default 表示默认值,如
String name() default "xujunTest"; 复制代码
/** * 这个类专门用来测试注解使用 * @author xujun */ //类成员注解 @MethodInfo (name="type",gid=Long.class) public class UserAnnotation { //类成员注解 @TestA(name="param",id=1,gid=Long.class) private Integer age; //构造方法注解 @TestA (name="construct",id=2,gid=Long.class) public UserAnnotation(){ } //类方法注解 @TestA(name="public method",id=3,gid=Long.class) public void a(){ Map<String,String> m = new HashMap<String,String>(0); } //类方法注解 @TestA(name="protected method",id=4,gid=Long.class) protected void b(){ Map<String,String> m = new HashMap<String,String>(0); } //类方法注解 @TestA(name="private method",id=5,gid=Long.class) private void c(){ Map<String,String> m = new HashMap<String,String>(0); } public void b(Integer a){ } } 复制代码
(1) 运行时 Annotation 指 @Retention 为 RUNTIME 的 Annotation,可手动调用下面常用 API 解析
method.getAnnotation(AnnotationName.class); method.getAnnotations(); method.isAnnotationPresent(AnnotationName.class); 复制代码
其他 @Target 如 Field,Class 方法类似
/* * 根据注解类型返回方法的指定类型注解 */ MethodInfo annotation = (MethodInfo) constructor .getAnnotation(MethodInfo.class); 复制代码
Annotation[] annotations = clazz.getAnnotations(); for (Annotation annotation : annotations) { MethodInfo methodInfo = (MethodInfo) annotation } 复制代码
/* * 判断构造方法中是否有指定注解类型的注解 */ boolean hasAnnotation = constructor .isAnnotationPresent(MethodInfo.class); if (hasAnnotation) { /* * 根据注解类型返回方法的指定类型注解 */ MethodInfo annotation = (MethodInfo) constructor .getAnnotation(MethodInfo.class); } 复制代码
public class ParseAnnotation { static String className="com.xujun.animation.test.UserAnnotation"; /** * 简单打印出UserAnnotation 类中所使用到的类注解 该方法只打印了 Type 类型的注解 * * @throws ClassNotFoundException */ public static void parseTypeAnnotation() throws ClassNotFoundException { Class clazz = Class.forName(className); Annotation[] annotations = clazz.getAnnotations(); for (Annotation annotation : annotations) { MethodInfo testA = (MethodInfo) annotation; System.out.println("id= /"" + testA.id() + "/"; name= /"" + testA.name() + "/"; gid = " + testA.gid()); } } /** * 简单打印出UserAnnotation 类中所使用到的方法注解 该方法只打印了 Method 类型的注解 * * @throws ClassNotFoundException */ public static void parseMethodAnnotation() { Method[] methods = UserAnnotation.class.getDeclaredMethods(); for (Method method : methods) { /* * 判断方法中是否有指定注解类型的注解 */ boolean hasAnnotation = method.isAnnotationPresent(MethodInfo.class); if (hasAnnotation) { /* * 根据注解类型返回方法的指定类型注解 */ MethodInfo annotation = method.getAnnotation(MethodInfo.class); System.out.println("method = " + method.getName() + " ; id = " + annotation.id() + " ; description = " + annotation.name() + "; gid= " + annotation.gid()); } } } /** * 简单打印出UserAnnotation 类中所使用到的方法注解 该方法只打印了 Method 类型的注解 * * @throws ClassNotFoundException */ public static void parseConstructAnnotation() { Constructor[] constructors = UserAnnotation.class.getConstructors(); for (Constructor constructor : constructors) { /* * 判断构造方法中是否有指定注解类型的注解 */ boolean hasAnnotation = constructor .isAnnotationPresent(MethodInfo.class); if (hasAnnotation) { /* * 根据注解类型返回方法的指定类型注解 */ MethodInfo annotation = (MethodInfo) constructor .getAnnotation(MethodInfo.class); System.out.println("constructor = " + constructor.getName() + " ; id = " + annotation.id() + " ; description = " + annotation.name() + "; gid= " + annotation.gid()); } } } public static void main(String[] args) throws ClassNotFoundException { parseTypeAnnotation(); parseMethodAnnotation(); parseConstructAnnotation(); } } 复制代码
运行以上测试程序,将可以看到以下输出结果
id= "0"; name= "type"; gid = class java.lang.Long method = c ; id = 5 ; description = private method; gid= class java.lang.Long method = b ; id = 4 ; description = protected method; gid= class java.lang.Long method = a ; id = 3 ; description = public method; gid= class java.lang.Long constructor = com.xujun.animationdemo.UserAnnotation ; id = 2 ; description = construct; gid= class java.lang.Long
源码下载地址:
java Type 详解
java 反射机制详解
注解使用入门(一)
Android 自定义编译时注解1 - 简单的例子
Android 编译时注解 —— 语法详解
带你读懂 ButterKnife 的源码
扫一扫,欢迎关注我的微信公众号 stormjun94(徐公码字) , 目前是一名程序员,不仅分享 Android开发相关知识,同时还分享技术人成长历程,包括个人总结,职场经验,面试经验等,希望能让你少走一点弯路。