注解

注解知识点

Java代码中使用注释是为了提升代码的可读性,也就是说,注释是给人看的(对于编译器来说没有意义)。注解可以看做是注释的“强力升级版",它可以向编译器、虚拟机等解释说明一些事情(也就是说它对编译器等工具也是“可读”的)。比如@Override注解,它的作用是告诉编译器它所注解的方法是重写的父类中的方法,这样编译器就会去检查父类是否存在这个方法,以及这个方法的签名与父类是否相同。

也就是说,注解是描述Java代码的代码,它能够被编译器解析,注解处理工具在运行时也能够解析注解。除了向编译器等传递一些信息,我们也可以使用注解生成代码。比如我们可以使用注解来描述我们的意图,然后让注解解析工具来解析注解,以此来生成一些”模板化“的代码。比如Hibernate、Spring等框架大量使用了注解,来避免一些重复的工作。注解是一种”被动“的信息,必须由编译器或虚拟机来“主动”解析它,它才能发挥自己的作用

元注解

元注解的作用就是负责注解其他注解。Java5.0定义了4个标准的meta-annotation类型,它们被用来提供对其它 annotation类型作说明

1. @Target

@Target说明了Annotation所修饰的对象范围,取值(ElementType)有:

CONSTRUCTOR:用于描述构造器
FIELD:用于描述域
LOCAL_VARIABLE:用于描述局部变量
METHOD:用于描述方法
PACKAGE:用于描述包
PARAMETER:用于描述参数
TYPE:用于描述类、接口(包括注解类型) 或enum声明

@Target({ElementType.FIELD, ElementType.METHOD})

2. @Retention
@Retention定义了该Annotation的“生命周期”,取值(RetentionPoicy)有:
SOURCE:在源文件中有效(即源文件保留)
CLASS:在class文件中有效(即class保留)
RUNTIME:在运行时有效(即运行时保留)

@Retention(RetentionPolicy.RUNTIME)

3. @Documented
@Documented用于描述其它类型的annotation应该被作为被标注的程序成员的公共API,因此可以被例如javadoc此类的工具文档化
Documented是一个标记注解,没有成员

4. @Inherited
@Inherited元注解是一个标记注解,@Inherited阐述了某个被标注的类型是被继承的
如果一个使用了@Inherited修饰的annotation类型被用于一个class,则这个annotation将被用于该class的子类

自定义注解

使用@interface自定义注解时,自动继承了java.lang.annotation.Annotation接口,由编译程序自动完成其他细节。在定义注解时,不能继承其他的注解或接口。@interface用来声明一个注解,其中的每一个方法实际上是声明了一个配置参数。方法的名称就是参数的名称,返回值类型就是参数的类型(返回值类型只能是基本类型、Class、String、enum)。可以通过default来声明参数的默认值。

定义注解格式:
  public @interface 注解名 {定义体}

注解参数的可支持数据类型:

1.所有基本数据类型(int,float,boolean,byte,double,char,long,short)
2.String类型
3.Class类型
4.enum类型
5.Annotation类型
6.以上所有类型的数组

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD, ElementType.METHOD})
public @interface SerializedName {
  String value();
  String[] alternate() default {};
}

注解处理器

1.运行时注解处理器
java.lang.reflect包中的所有API都支持读取运行时Annotation的能力,即属性为@Retention(RetentionPolicy.RUNTIME)的注解。

//获取所有属性  
Field[] fields = clazz.getDeclaredFields();  

for(Field field : fields){  
//根据注解的类型做不同的处理  
if(field.isAnnotationPresent(XXX.class)){  
    //获取该类型的注解  
    XXX xx = field.getAnnotation(XXX.class);  
    //获取注解中元素值  
    xxx.方法名;  
}else if(field.isAnnotationPresent(FruitColor.class)){ 
    something
}

2.编译时注解处理器
采用APT(Annotation Processor Tool)
编译时注解处理器编译一个注解时,主要分2步

  • 继承AbstractProcessor,实现自己的注解处理器
  • 注册处理器,并打包成jar

4个重要方法,其中process是必须实现的抽象方法
init(ProcessingEnvironment processingEnv) 该方法由注解处理器自动调用,其中ProcessingEnvironment类提供了很多有用的工具类:Filter,Types,Elements,Messager等

getSupportedAnnotationTypes() 该方法返回字符串的集合表示该处理器用于处理那些注解

getSupportedSourceVersion() 该方法用来指定支持的Java版本,一般来说我们都是支持到最新版本,因此直接返回SourceVersion.latestSupported()即可

process(Set annotations, RoundEnvironment roundEnv) 该方法是注解处理器处理注解的主要地方,我们需要在这里写扫描和处理注解的代码,以及最终生成的java文件。其中需要深入的是RoundEnvironment类,该用于查找出程序元素上使用的注解

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容