注解

Smile_slime_47

注解

注解概念


注解(Annotation)是在JDK1.5加入的特性,是一种特殊的注释,和注释不同的是,在编译时注解会被一同编译进Class文件中,并且可以由其他类通过反射来调用Class对象的注解内容。简单地说:注解是一种可以被其他类读取的标注

无论是对于程序员还是编译器,注解都不会产生任何的影响:它既不像注释那样用于给程序员标明代码作用,也不像代码那样指示机器如何工作。注解唯一的作用就是被其他类读取

通常来说,这个其他类分为两种:编译器和框架:

  • 一部分注解用于指示编译器工作,如@Override、@SuppressWarnings等
  • 另一部分注解用于指示框架工作,如@Configuration、@Component等

JDK注解


JDK本身提供了少数注解,其中@SafeVarargs在JDK1.7中加入,@FunctionalInterface和@Repeatable在JDK1.8中加入

@Override

指示该方法重写了父类方法,若没有正确重写则会报错

@Deprecated

指示该方法已过时,使用会警告

@SuppressWarnings

忽视编译器给出的任何警告

@SafeVarargs

忽视使用泛型参数的方法/构造函数的警告

@FunctionalInterface

标注一个函数式接口,即仅包含一个方法的接口

@Repeatable

指示一个注解可以被重复在同一个位置使用多次

定义注解


我们可以自己根据需求创建新的注解,通过关键字@interface创建,并结合部分元注解进行设定

举例来说:

1
2
3
4
5
6
7
8
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Report {
//参数列表,其中value为默认参数
int type() default 0;
String level() default "info";
String value() default "";
}

元注解,即修饰在注解上的注解。这类注解一般用于指示注解的属性

@Retention

注解的生命周期,参数有:源代码(SOURCE)Class文件(CLASS)和运行时(RUNTIME)

@Documented

注解是否包含于说明文档中

@Target

注解的标注位置,参数有:TYPE(类), FIELD(字段), METHOD(方法), PARAMETER(参数), CONSTRUCTOR(构造器), LOCAL_VARIABLE, ANNOTATION_TYPE, PACKAGE, TYPE_PARAMETER, TYPE_USE

@Inherited

指示该注解具有继承性,即使用@Inherited的注解会将类的该注解继承给它的子类

读取注解


读取注解的方式和注解的生命周期相关:

  • 对于@Retention为SOURCE的注解,在编译后被丢失,一般只有编译器使用
  • 对于@Retention为CLASS的注解,保存在Class文件中,但在被JVM读取后被丢失
  • 对于@Retention为RUNTIME的注解,会保存在Class文件中,并且在运行时仍可被读取

通过反射读取注解

我们可以通过一系列反射类提供的方法判断一个反射类是否包含某注解,其中参数传入对应注解的Class对象

  • Class.isAnnotationPresent(Class annotation)
  • Field.isAnnotationPresent(Class annotation)
  • Method.isAnnotationPresent(Class annotation)
  • Constructor.isAnnotationPresent(Classannotation)

此外还可以通过一系列方法读取一个反射类包含的注解,其中参数传入对应注解的Class对象

  • Class.getAnnotation(Class annotation)
  • Field.getAnnotation(Class annotation)
  • Method.getAnnotation(Class annotation)
  • Constructor.getAnnotation(Class annotation)

在通过上述方法获取到反射类的注解的封装对象后,我们就可以读取注解中的参数了:

1
2
3
4
// 获取Person定义的@Report注解:
Report report = Person.class.getAnnotation(Report.class);
int type = report.type();
String level = report.level();
Comments