元数据(MetaData = Annotation),Annotation是代码里的特殊标记,这些标记可以在编译、类加载、运行时被读取,并执行相应的处理。通过使用注解,程序开发人员可以在不改变原有逻辑的情况下,在源文件中嵌入一些补充的信息,代码分析工具、开发工具和部署工具可以通过这些补充信息进行验证或进行部署。
Annotation提供了一种为程序元素设置元数据的方法,可以像修饰符一样去修饰包、类、构造器、方法或成员变量、参数、局部变量的声明,这些信息被存储在Annotation的”name=value”对中。
Annotation是一个接口,程序可以通过反射来获取指定程序元素的Annotation对象,然后通过Annotation对象来获取注解里的元数据,Annotation不影响程序代码的执行,无论增加、删除Annotation,代码都始终如一地执行
1 基本Annotation
- 基本的Annotation是:
- @Override
- @Deprecated
- @SuppressWarning
- @SafeVarargs
- @FunctionInterface
- 使用Annotation时要在其前面增加@符号,并把Annotation当成一个修饰符使用,用于修饰它支持的程序元素
1.1 限定重写父类方法:@Override
- @Override就是用来指定方法覆载的,它可以强制一个子类必须必须覆盖父类的方法。
- @Override的作用是告诉编译器检查这个方法,保证父类要包含一个该方法重写的方法,否则就会编译出错
- @Override主要是帮助程序员避免一些低级错误
- @Override只能修饰方法,不能修饰其他程序元素
1.2 标记已过时:@Deprecated
- @Deprecated用于表示某个程序元素(类、方法等)已过时,当其他程序使用已过时的类、方法时,编译器将会给出警告
- @Deprecated可修饰方法、类、接口等
1.3 抑制编译器警告:@SuppressWarning
- @SuppressWarning指示被该Annotation修饰的程序元素(以及该元素的所有子元素)取消显示指定的编译器警告
- 当使用@SuppressWarning Annotation来关闭编译器警告时,一定要在括号里使用name=value的形式为该Annotation的成员变量设置值
1.4 Java 7的“堆污染”警告与@SafeVarargs
- 当把一个不带泛型的对象赋给一个带泛型的变量时,往往会发生堆污染
- 抑制堆污染警告的方法:
- 使用@SafeVarargs修饰引发该警告的方法或构造器
- 使用@SuppressWarnings(“unchecked”)修饰
- 编译时使用-Xlint:varargs选项
1.5 Java 8的函数式接口与@FunctionInterface
- @FunctionInterface用来指定某个接口必须是函数式接口
- @FunctionInterface只是告诉编译器检查这个接口,保证该接口只能包含一个抽象方法,否则就会编译出错,主要是帮助程序员避免一些低级错
2 元Annotation
2.1 @Retention
- @Retention只能用于修饰Annotation定义,用于指定被修饰的Annotation可以保留多长时间,@Retention包含一个RetentionPolicy类型的value成员变量,所以使用@Retention时必须为该value成员变量指定值。value成员变量的值只能是下面的三个:
- RetentionPolicy.CLASS:编译器将把Annotation记录在class文件中。当运行Java程序时, JVM不可获取Annotation信息,这是默认值。
- RetentionPolicy.RUNTIME:编译器将把Annotation记录在class文件中,当运行Java程序时,JVM也可获取Annotation信息,程序可以通过反射获取该Annotation信息
- RetentionPolicy.SOURCE:Annotation只保存在源代码中,编译器直接丢弃这种Annotation
- 指定value值方法:
- @Retention(value = RetentionPolicy.RUNTIME)
- @Retention(RetentionPolicy.RUNTIME)
2.2 @Target
- @Target只能用于修饰Annotation定义,用于指定被修饰的Annotation能用于修饰哪些程序单元,@Target包含一个value成员变量,value成员变量的取值:
- ElementType.ANNOTATION_TYPE:指定该策略的Annotation只能修饰Annotation
- ElementType.CONSTRUCTOR:指定该策略的Annotation只能修饰构造器
- ElementType.FIELD:指定该策略的Annotation只能修饰成员变量
- ElementType.LOCAL_VARIABLE:指定该策略的Annotation只能修饰局部变量
- ElementType.METHOD:指定该策略的Annotation只能修饰方法定义
- ElementType.PACKAGE:指定该策略的Annotation只能修饰包定义
- ElementType.PARAMETER:指定该策略的Annotation只能修饰参数
- ElementType.TYPE:指定该策略的Annotation只能修饰类、接口或枚举定义
- 指定value值方法:
- @Target(value = ElementType.TYPE)
- @Retention(ElementType.TYPE)
2.3 @Documented
- @Documented用于指定被该元Annotation修饰的Annotation类将别javadoc工具提取成文档,如果定义Annotation类是使用了@Documented修饰,则所有使用该Annotation修饰的程序元素的API文档终将会包含该Annotation说明
2.4 @Inherited
- @Inherited元Annotation指定被它修饰的Annotation将具有继承性——如果某个类是用来@Xxx注解修饰,则其子类将自动被@Xxx修饰
public class AnnotationTest {
//使用@Retention,定义下面的RetentionTest Annotation保留到运行时
@Retention(RetentionPolicy.RUNTIME)
@interface RetentionTest {
}
//使用@Target,定义下面的TargetTest Annotaion只能修饰方法
@Target(ElementType.METHOD)
@interface TargetTest {
}
//使用@Documented,定义下面的DocumentedTest Annotation将被javadoc工具提取
@Documented
@interface DocumentedTest {
}
//使用@Inherited,定义下面的InheritedTest Annotation具有继承性
@Inherited
@interface InheritedTest {
}
}
3 自定义Annotation
- 定义新的Annotation类型使用@interface关键字,默认情况下可用于修饰类、方法、变量、接口等定义,Annotation还可以带成员变量,成员变量以无形参的方法形式来声明,其方法名和返回值定义了该成员变量的名字和类型,Annotation定义了成员变量的话,使用的时候就应该指定值,也可以使用default指定初始值,语法格式如下:
//定义一个简单的Annotation类型
public @interface Test{
//
String name() default "123";
int age() default 123;
}
- 根据Annotation是否可以包含成员变量,可以把Annotation分为如下两类:
- 标记Annotation:无成员变量,利用自身的存在与否来提供信息
- 元数据Annotation:包含成员变量,可以接受更多的元数据