原创

【每天十分钟JAVA快速入门】(十八)注解

注解(Annotation

注解是Java5.0开始引入的一个概念,之后在实际运用中被广泛采用,比如现在的程序员使用在使用一些主流的框架时已经习惯于用注解来代替xml配置文件了。注解(Annotation)和注释(Comments)的区别在于,注释是写给人看的,用于描述代码的核心功能与逻辑,而注解是写给编译器、工具类软件以及程序本身使用的,类似于给特定代码做上标签,相关的使用者识别到这些标签后就知道需要做什么。

定义
定义一个注解与接口类似,使用interface关键字,不过需要在前面加上一个@符号:
public @interface SampleAnnotation {
}

使用
使用注解也很简单,在需要打标签的地方使用@+注解名称就可以了:
@SampleAnnotation
public class SampleClass {
}
这样就给Student类打上了一个SampleAnnotion的标签,不过现在看起来好像什么也做不了的样子,不用急,我们继续往下学习。

属性
注解只有属性,类似与成员变量,但是定义的方式又类似于无参的方法,例如:
public @interface SampleAnnotation {
int id() default 1;
String type() default "S";
}
上面的注解有两个属性,id和type。使用时可以给他们赋值:
@SampleAnnotation(id = 1,type = "S")
public class SampleClass {
}
定义属性时可以使用default设置默认值。
public @interface SampleAnnotation {
int id() default 1;
String type() default "S";
}

元注解
元注解就是注解的注解,定义了用于描述注解本身的一些基本属性,有@Retention、@Documented、@Target、@Inherited、@Repeatable 5 种。

@Retention 定义了注解的保留时段,类似于有效期,例如:
RetentionPolicy.SOURCE 注解只在源码阶段保留,在编译时它将被忽视。
RetentionPolicy.CLASS 注解只被保留到编译期,并不会被加载到虚拟机中。
RetentionPolicy.RUNTIME 注解可以保留到程序运行的时候,它会被加载进入到虚拟机中,在运行时可以获取到它们。

@Documented Javadoc可以包含注解中的元素。

@Target 指定注解运用的目标,就是指定注解可以用在什么地方,例如:
ElementType.ANNOTATION_TYPE 可以给一个注解进行注解
ElementType.CONSTRUCTOR 可以给构造器进行注解
ElementType.FIELD 可以给成员变量进行注解
ElementType.LOCAL_VARIABLE 可以给局部变量进行注解
ElementType.METHOD 可以给方法进行注解
ElementType.PACKAGE 可以给一个包进行注解
ElementType.PARAMETER 可以给一个方法的参数进行注解
ElementType.TYPE 可以给一个类型进行注解,比如类、接口、枚举

@Inherited 如果父类使用的注解包含@Inherited,则子类自动继承父类的注解。

@Repeatable 使用时可以给注解设置多个值,例如:我们写了一篇文章需要发布,先定义一个文章的类型(Category),假设为Java后端,同时这个类型的文章标签(Tag)有多个,假设为Java,Spring,Spring Boot,那么如何定义和使用注解来描述这样的情景呢:
定义一个注解容器(Category),实际上它本身就是一个注解,属性包含一个Tag的数组:
public @interface Category {
Tag[] value();
}
定义Tag注解,并设置@Repeatable将容器注解设置为Category.class:
@Repeatable(Category.class)
public @interface Tag {
String value();
}
现在就可以使用了:
@Tag("Java")
@Tag("Spring")
@Tag("Spring Boot")
public class Article {
}

Java预制注解
其实我们平时开发过程中多多少少已经接触到一些注解了,有一部分是Java预制的注解,例如@Deprecated(废弃不用的方法)、@Override(子类覆盖父类的方法)、@SuppressWarnings(忽略警告信息)等等,这里就不详细说明了。

注解识别
上面说了这么多其实还是没有说明注解定义好了到底该怎样使用呢?其实关键在于如何识别注解,就像超市的每个商品上都贴好了条码标签,工作人员使用扫描设备就可以识别标签并查看商品详情了。Java中是如何识别注解的呢?使用的关键技术就是之前学习的反射。
Class类有一个方法isAnnotationPresent,该方法判断该类是否使用了否个注解:
@SampleAnnotation()
public class SampleClass {
public static void main(String[] args) {
boolean annotationPresent = SampleClass.class.isAnnotationPresent(SampleAnnotation.class);
System.out.println(annotationPresent);
}
}
由于需要在运行时进行识别注解,因此需要设置@Retention为运行时:
@Retention(RetentionPolicy.RUNTIME)
public @interface SampleAnnotation {
int id() default 1;
String type() default "S";
}
获取到相应的注解后就可以访问到注解属性了:
if(annotationPresent){
SampleAnnotation sampleAnnotation = SampleClass.class.getAnnotation(SampleAnnotation.class);
System.out.println(sampleAnnotation.id());
System.out.println(sampleAnnotation.type());
}

注解并不属于它打标签的业务代码本身的一部分,它对于构建非侵入式软件非常有作用,在目前的一些主流框架如Spring系列,Mybatis,以及日志框架中的应用非常广泛。

正文到此结束