Java注解详解
Annotation基础
1、什么是annotation
官网的解释:
<blockquote>Annotations, a form of metadata, provide data about a program that is not part of the program itself. Annotations have no direct effect on the operation of the code they annotate.</blockquote>
注解:一种元数据形式,提供不属于程序本身的程序的数据,Annotations对它所注解的代码的操作没有直接的影响。
注解的作用:
- 为编译器提供信息 — 编译器可以使用注解来检查错误、取消警告等
- 编译时和部署时处理 — 可以使用程序来处理注解从而生成代码、xml文件等
- 运行时处理 — 运行时动态的检查注解信息来执行不同的逻辑
注解的分类
-
标准 Annotation,例如@Override,@ Deprecated, @SuppressWarnings
标准 Annotation 是指 Java 自带的几个 Annotation,上面三个分别表示重写函数,不鼓励使用(有更好方式、使用有风险或已不在维护),忽略某项 Warning -
元Annotation,例如@Retention, @Target, @Inherited, @Documented
元 Annotation 是指用来定义 Annotation 的 Annotation -
自定义 Annotation
自定义 Annotation 表示自己根据需要定义的 Annotation,定义时需要用到上面的元 Annotation;根据作用域分为源码时、编译时、运行时 Annotation.
2、元注解
元注解的作用就是注解其他注解。Java中定义了4个标准的meta-annotation类型,用以对其他的annotation类型做说明,分别是@Target,@Retention,@Documented,@Inherited
@Target
表明Annotation所修饰的Java元素类型
取值(ElementType):
- ElementType.ANNOTATION_TYPE: 表明注解可以被用于其他注解
- ElementType.CONSTRUCTOR:表明注解可以用于构造函数
- ElementType.FIELD:表明注解可以用于类的成员变量和属性
- ElementType.LOCAL_VARIABLE:表明注解可以用于局部变量
- ElementType.METHOD:表明注解可以用于方法
- ElementType.PACKAGE:表明注解可以用于包的声明
- ElementType.PARAMETER:表明注解可以用于方法的参数
- ElementType.TYPE:表明注解可以用于类、接口、枚举等所有Class类型
如果没有声明,可以修饰所有
** @Retention**
表示需要在什么级别保存该注释信息,用于描述注解的生命周期
取值(RetentionPolicy):
- RetentionPolicy.SOURCE: 注解的作用域限制在源码.java文件级别,编译器会直接忽略它.
- RetentionPolicy.CLASS:注解的作用域限制在编译期间.class文件级别,JVM运行时会直接忽略.
- RetentionPolicy.RUNTIME: 作用域能够延伸到JVM运行时
默认为CLASS
** @ Documented** 标记注解,没有成员
用于描述其它类型的annotation应该被作为标注的程序成员的公共api,可以文档化
@Inherited 标记注解
用该注解修饰的注解,会被子类继承。如果一个使用了@Inherited修饰的annotation类型被用于一个class,则这个annotation将被用于该class的子类。
3、自定义注解
自定义注解主要包括一下两个方面
- 注解的元数据-包括注解的作用域、作用对象等
- 注解的元素声明-主要声明注解的属性(注解的属性的数据类型只能为基本类型、String类型、Class类型、Annotation类型、enum类型、以上所有类型的一维数组)
接口AnnotatedElement包含了常用的Annotation相关的API,其所有已知实现类有:AccessibleObject, Class, Constructor, Field, Method,Package
AnnotatedElement常用方法如下:
//如果存在该元素的指定类型的注解,则返回这些注解,否则返回 null。
<T extends Annotation> T getAnnotation(Class<T> annotationClass)
//返回此元素上存在的所有注解。(如果此元素没有注解,则返回长度为零的数组。)
Annotation[] getAnnotations()
//返回直接存在于此元素上的所有注释,不包含继承的注解
Annotation[] getDeclaredAnnotations()
//如果指定类型的注释存在于此元素上,则返回 true,否则返回 false
boolean isAnnotationPresent(Class<? extends Annotation> annotationClass)
自定义注解示例:
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@Inherited
public @interface MethodInfo {
String author() default "trinea@gmail.com";
String date();
int version() default 1;
}```
这里是 MethodInfo 的实现部分
(1). 通过 @interface 定义,注解名即为自定义注解名
(2). 注解配置参数名为注解类的方法名,且:
* 所有方法没有方法体,没有参数没有修饰符,实际只允许 public & abstract 修饰符,默认为 public,不允许抛异常
* 方法返回值只能是基本类型,String, Class, annotation, enumeration 或者是它们的一维数组
* 若只有一个默认属性,可直接用 value() 函数。一个属性都没有表示该 Annotation 为 Mark Annotation
(3). 可以加 default 表示默认值
参考文章:
[官方文档](https://docs.oracle.com/javase/tutorial/java/annotations/index.html)
[Android公共技术点之一-Java注解](http://yeungeek.com/2016/04/25/Android%E5%85%AC%E5%85%B1%E6%8A%80%E6%9C%AF%E7%82%B9%E4%B9%8B%E4%B8%80-Java%E6%B3%A8%E8%A7%A3/)
[公共技术点之 Java 注解 Annotation](http://b.codekk.com/blogs/detail/54cfab086c4761e5001b253b/)
[深入理解Java:注解(Annotation)自定义注解入门](http://www.cnblogs.com/peida/archive/2013/04/24/3036689.html)
[Java注解与注解处理器初探](https://juejin.im/entry/595f9c4df265da6c33240804)
著名使用注解的库:
[butterknife](https://github.com/JakeWharton/butterknife)-使用annotationProcess编译时生成代码
[retrofit](https://github.com/square/retrofit)-运行时注解
[dagger](https://github.com/google/dagger)-使用annotationProcess编译时生成代码
[hugo](https://github.com/JakeWharton/hugo)-使用aspectj编译时生成代码