前言
Annotation——注解,JDK1.5新增加的功能。它能够添加到 Java 源代码的语法元数据。类、方法、变量、参数、包都可以被注解,可用来将信息元数据与程序元素进行关联。目前很多开源库都使用到了注解,最熟悉的ButtonKnife中的@ViewInject(R.id.x)就可以替代findViewId,不懂这一块技术的同学第一眼看上去肯定会一脸懵逼,下面会手把手带大家写出ButtonKnife的注解使用。使用注解可以简化代码,提高开发效率。本文简单介绍下注解的使用,并对几个 Android 开源库的注解使用原理进行简析。
1、作用
- 标记,用于告诉编译器一些信息 ;
- 编译时动态处理,如动态生成代码 ;
- 运行时动态处理,如得到注解信息。
2、分类
- 标准 Annotation, 包括 Override, Deprecated, SuppressWarnings。也都是Java自带的几个 Annotation,上面三个分别表示重写函数,不鼓励使用(有更好方式、使用有风险或已不在维护),忽略某项 Warning;
- 元 Annotation ,@Retention, @Target, @Inherited, @Documented。元 Annotation 是指用来定义 Annotation 的 Annotation,在后面 Annotation 自定义部分会详细介绍含义;
- 自定义 Annotation , 表示自己根据需要定义的 Annotation,定义时需要用到上面的元 Annotation 这里只是一种分类而已,也可以根据作用域分为源码时、编译时、运行时 Annotation。通过 @interface 定义,注解名即为自定义注解名。
一、自定义注解
例如,注解@MethodInfo:
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@Inherited
public @interface MethodInfo {
String author() default "annotation@gmail.com";
String date();
int version() default 1;
}
使用到了元Annotation:
- @Documented 是否会保存到 Javadoc 文档中 ;
- @Retention 保留时间,可选值 SOURCE(源码时),CLASS(编译时),RUNTIME(运行时),默认为 CLASS,值为 SOURCE 大都为 Mark Annotation,这类 Annotation 大都用来校验,比如 Override, Deprecated, SuppressWarnings ;
- @Target 用来指定修饰的元素,如 CONSTRUCTOR:用于描述构造器、FIELD:用于描述域、LOCAL_VARIABLE:用于描述局部变量、METHOD:用于描述方法、PACKAGE:用于描述包、PARAMETER:用于描述参数、TYPE:用于描述类、接口(包括注解类型) 或enum声明。
- @Inherited 是否可以被继承,默认为 false。
注解的参数名为注解类的方法名,且:
- 所有方法没有方法体,没有参数没有修饰符,实际只允许 public & abstract 修饰符,默认为 public ,不允许抛异常;
- 方法返回值只能是基本类型,String, Class, annotation, enumeration 或者是他们的一维数组;
- 若只有一个默认属性,可直接用 value() 函数。一个属性都没有表示该 Annotation 为 Mark Annotation。
public class App {
@MethodInfo(
author = “annotation.cn+android@gmail.com”,
date = "2011/01/11",
version = 2)
public String getAppName() {
return "appname";
}
}
调用自定义MethodInfo 的示例,这里注解的作用实际是给方法添加相关信息: author、date、version 。
二、实战注解Butter Knife
首先,先定义一个ViewInject注解。
public @interface ViewInject {
int value() default -1;
}
紧接着,为刚自定义注解添加元注解。