Annotation 被称为注解,在Java开发中是至关常见的,经过注解,咱们能够简化代码提升开发效率。例如Override Annotation,这个应该算是在开发过程当中使用最多的注解了。下面这个例子是Android Activity的onCreate方法最经常使用的注解:数组
@Override public void onCreate(Bundle savedInstanceState);
An annotation is a form of metadata, that can be added to Java source code. Classes, methods, variables, parameters and packages may be annotated. Annotations have no direct effect on the operation of the code they annotate.app
译文:ide
Annotation (注解) 表示的是可以添加到Java源代码的语法元数据。类、方法、变量、参数、包均可以被注解,可用来将信息元数据和程序元素进行关联。函数
a.标记做用,用于告诉编译器一些信息ui
b.编译时动态处理,如动态生成代码spa
c.运行时动态处理,如获得注解信息code
这三个做用对应着后面自定义Annotation时说的@Retention三种值分别表示的Annotationorm
包括 Override, Deprecated, SuppressWarnings,标准 Annotation 是指 Java 自带的几个 Annotation,上面三个分别表示重写函数,不鼓励使用(有更好方式、使用有风险或已不在维护),忽略某项 Warning对象
@Retention, @Target, @Inherited, @Documented,元 Annotation 是指用来定义 Annotation 的 Annotation。blog
—@Documented:是否会保存到 Javadoc 文档中
—@Retention:保留时间,可选值 SOURCE(源码时),CLASS(编译时),RUNTIME(运行时),默认为 CLASS,值为 SOURCE 大都为 Mark Annotation,这类 Annotation 大都用来校验,好比 Override, Deprecated, SuppressWarnings
—@Target:能够用来修饰哪些程序元素,如 TYPE, METHOD, CONSTRUCTOR, FIELD, PARAMETER 等,未标注则表示可修饰全部。
—@Inherited: 是否能够被继承,默认为 false
自定义 Annotation 表示自己根据须要定义的 Annotation,定义时须要用到上面的元 Annotation,这里只是一种分类而已,也能够根据做用域分为源码时、编译时、运行时 Annotation。
a.定义
下面实现了一个自定义注解—MethodInfo:
@Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) @Inherited public @interface MethodInfo { String author() default "renhui"; String date(); int version() default 1; }
这里是 的实现部分
(1). 经过 @interface 定义,注解名即为自定义注解名
(2). 注解配置参数名为注解类的方法名,且:
a. 全部方法没有方法体,没有参数没有修饰符,实际只容许 public & abstract 修饰符,默认为 public ,不容许抛异常
b. 方法返回值只能是基本类型,String, Class, annotation, enumeration 或者是他们的一维数组
c. 若只有一个默认属性,可直接用 value() 函数。一个属性都没有表示该 Annotation 为 Mark Annotation
(3). 能够加 default 表示默认值
b.调用
public class App { @MethodInfo( author = “renhui”, date = "2016/01/14", version = 1) public String getAppName() { return "demo"; } }
这里是调用自定义 Annotation——MethodInfo 的示例,MethodInfo Annotation 做用为给方法添加相关信息,包括 author、date、version
c.解析
(1) 运行时 Annotation 指 @Retention 为 RUNTIME 的 Annotation,可手动调用下面经常使用 API 解析
method.getAnnotation(AnnotationName.class); method.getAnnotations(); method.isAnnotationPresent(AnnotationName.class);
其余 @Target 如 Field,Class 方法相似
getAnnotation(AnnotationName.class) 表示获得该 Target 某个 Annotation 的信息,由于一个 Target 能够被多个 Annotation 修饰
getAnnotations() 则表示获得该 Target 全部 Annotation
isAnnotationPresent(AnnotationName.class) 表示该 Target 是否被某个 Annotation 修饰
(2) 解析示例以下:
public static void main(String[] args) { try { Class cls = Class.forName("*.App"); for (Method method : cls.getMethods()) { MethodInfo methodInfo = method.getAnnotation( MethodInfo.class); if (methodInfo != null) { System.out.println("method name:" + method.getName()); System.out.println("method author:" + methodInfo.author()); System.out.println("method version:" + methodInfo.version()); System.out.println("method date:" + methodInfo.date()); } } } catch (ClassNotFoundException e) { e.printStackTrace(); } }
(1) 编译时 Annotation 指 @Retention 为 CLASS 的 Annotation,甴 apt(Annotation Processing Tool) 解析自动解析。须要作的
a. 自定义类集成自 AbstractProcessor
b. 重写其中的 process 函数
这块不少同窗不理解,实际是 apt(Annotation Processing Tool) 在编译时自动查找全部继承自 AbstractProcessor 的类,而后调用他们的 process 方法去处理
(2) 假设以前自定义的 MethodInfo 的 @Retention 为 CLASS,解析示例以下:
@SupportedAnnotationTypes({ "*.MethodInfo" }) public class MethodInfoProcessor extends AbstractProcessor { @Override public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment env) { HashMap<String, String> map = new HashMap<String, String>(); for (TypeElement te : annotations) { for (Element element : env.getElementsAnnotatedWith(te)) { MethodInfo methodInfo = element.getAnnotation(MethodInfo.class); map.put(element.getEnclosingElement().toString(), methodInfo.author()); } } return false; } }
SupportedAnnotationTypes 表示这个 Processor 要处理的 Annotation 名字。
process 函数中参数 annotations 表示待处理的 Annotations,参数 env 表示当前或是以前的运行环境
process 函数返回值表示这组 annotations 是否被这个 Processor 接受,若是接受后续子的 rocessor 不会再对这个 Annotations 进行处理
使用编译时注解很实用的例子:作代码混淆时能够经过添加编译时注解并配合配置文件,达到指定的类、方法、对象等不进行混淆。