注解Annotation
一、简介
从JDK5开始,Java增加了对元数据的支持,也就是Annotation(注释),其实是代码里的特殊标记,这些标记可以在编译、类加载、运行时被读取,并执行相应的处理。
注解提供了一种为程序元素设置元数据的方法,从某些方面来看,注解就像修饰符一样,可用于修饰包、类、构造器、方法、成员变量、参数、局部变量的声明,这些信息被存储在注解的“name=value”对中。
5个基本的注解如下:都是在java.lang下包
1.1 重写父类@Override
@Override就是用来指定方法覆载的,它可以强制一个子类必须覆盖父类的方法。
1.2 标记已过时@Deprecated
@Deprecated用于表示某个程序元素(类、方法等)已过时,当其他程序使用已过时的类、方法时,编译器将会给出警告。
1.3 抑制编译器警告@Suppress Warnings
@Suppress Warnings指示被该注解修饰的程序元素取消显示指定的编译器警告。@Suppress Warnings会一直作用于该程序元素的所有子元素。
1.4 “堆污染”警告 @Safe Varargs
1.5 函数式接口@FunctionalInterface
如果接口中只有一个抽象方法(可以包含多个默认方法或多个static方法),该接口就是函数式接口。@FunctionalInterface就是用来指定某个接口必须是函数式接口。
因为@FunctionalInterface是告诉编译器检查这个接口,保证该接口只能包含一个抽象方法,否则就会编译出错。
下面的写到test()才不报错
@FunctionalInterface
public interface FunInterface {
static void foo(){
System.out.println("foo");
}
default void bar(){
System.out.println("var");
}
void test(); //只定义一个抽象方法
}
二、JDK的元注解
在java.lang.annotation包下
2.1 @Retention
@Retention只能用于修饰注解定义,用于指定被修饰的注解可以保留多长时间,@Retention包含一个RetentionPolicy类型的value成员变量,所以使用@Retention时必须为该value成员变量指定值。
value成员变量的值只能是如下三个:
RetentionPolicy.CLASS:编译器将把注解记录在class文件中。当运行Java程序时,JVM不可获取注解信息。这是默认值。
RetentionPolicy.RUNTIME:编译器将把注解记录在class文件中。当运行Java程序时,JVM也可获取注解信息,程序可以通过反射获取该注解信息。
RetentionPolicy.SOURCE:注解只保留在源代码中,编译器直接丢弃这种注解。
//定义下面的@Testable注解保留到运行时
@Retention(value=RetentionPolicy.RUNTIME)
public @interface Testable()
//定义下面的@Testable编译器直接丢弃
@Retention(value=RetentionPolicy.SOURCE)
public @interface Testable()
2.2 @Target
@Target也只能修饰注解定义,它用于指定被修饰的注解能用于修饰哪些程序单元。@Target元注解也包含一个名为value的成员变量
ElementType.ANNOTATION TYPE:指定该策略的注解只能修饰注解。
ElementType.CONSTRUCTOR:指定该策略的注解只能修饰构造器。
ElementType.FIELD:指定该策略的注解只能修饰成员变量。
ElementType.LOCAL_VARIABLE:指定该策略的注解只能修饰局部变量。
ElementType.METHOD:指定该策略的注解只能修饰方法定义。
ElementType.PACKAGE:指定该策略的注解只能修饰包定义。
ElementType.PARAMETER:指定该策略的注解可以修饰参数。
ElementType.TYPE:指定该策略的注解可以修饰类、接口(包括注解类型)或枚举定义。
//只能修饰成员变量
@Target (ElementType.FIELD)
public @interface ActionListenerFor()
//@Testable注解只能修饰方法。
@Target (ElementType.METHOD)
pubiic @interface Testable
2.3 @Documented
@Documented用于指定被该元注解修饰的注解类将被javadoc工具提取成文档,如果定义注解类时用了@Documented修饰,则所有使用该注解修饰的程序元素的API文档中将会包含该注解说明。
@Retention (RetentionPolicy.RUNTIME)
@Target (ElementType.METHOD)
@Documented //定义Testable注解将被javadoc工具提取
public @interface Testable
{
}
2.4 @Inherited
@Inherited元注解指定被它修饰的注解将具有继承性一如果某个类使用了@Xxx注解(定义该注解时使用了@Inherited修饰)修饰,则其子类将自动被@Xxx修饰。
@Inheritable //修饰base类
class Base{
}
//只是继承,未使用,注解有继承性,子类也有
public class InheritableTest extends Base{
public static void main(String[] args) {
System.out.println(InheritableTest.class.isAnnotationPresent (Inheritable.class));
}
}
三、自定义注解
3.1 定义注解
定义新的注解类型使用@interface关键字(在原有的interface关键字前增加@符号)
//定义一个简单的注解类型
public @interface Test
}
定义了该注解之后,就可以在程序的任何地方使用该注解,使用注解的语法非常类似于public、final这样的修饰符,通常可用于修饰程序中的类、方法、变量、接口等定义。
3.2 提取注解信息
3.3 使用注解
3.4 重复注解
3.5 类型注解
四、编译时处理注解
APT是一种注解处理工具,它对源代码文件进行检测,并找出源文件所包含的注解信息,然后针对注解信息进行额外的处理。
使用APT工具处理注解时可以根据源文件中的注解生成额外的源文件和其他的文件,APT还会编译生成的源代码文件和原来的源文件,将它们一起生成class文件。
//下面是修饰标识属性的@Id注解。
@Target (ElementType.FIELD)
@Retention(RetentionPolicy.SOURCE)
@Documented
public @interface Id{
String column ();
String type();
String generator();
}
//下面是修饰标识类、接口注解。
@Target (ElementType.TYPE)
@Retention(RetentionPolicy.SOURCE)
@Documented
public @interface Id{
String column ();
}
//修饰普通成员属性的注解。
@Target (ElementType.FIELD)
@Retention(RetentionPolicy.SOURCE)
@Documented
public @interface Property
String column ()
String type();