(三):自定义注解的配置使用

注解Annotation全解析(二):自定义注解的定义一文中,
我们学会了定义一个自己的注解。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
import java.lang.annotation.ElementType;
import java.lang.annotation.Target;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
public @interface LovoAnnotation{
public String name();
int age() default 18;
int[] scores();
}

那么,定义好了一个注解该如何使用呢?这就是我们接下来要探讨的。

回顾

首先,在前面我们说过,在Oracle的官方文档中,注解Annotation的定义是:

Annotation 是一种能够被书写到Java源代码中的元数据(metadata:描述数据的数据)形式。类、方法、变量、参数和包都可以使用它来进行描述。Annotation不会对它描述的代码操作有任何的直接影响。

从这个定义中,我们可以看到注解是用来修饰Java源代码中的各种元素的,相当于起到一个配置作用。
其次,我们从定义注解的语法可以看到,无论是注解内容中定义的注解类型元素,还是各种元注解的作用,都是用来制定这个自定义注解可以配置什么值,可以配置在哪里,可以在什么阶段读取到这个配置。
最后,我们再来看看这幅图:

可以看到,定义注解只是做到了第一步,接下来就要配置它,最后能够在运行期读到这个编码期给出的配置数据。
接下来我们就来学习如何在另一个类当中配置它

配置Annotation

我们就利用这里定义的LovoAnnotation来进行学习吧。

首先,我们要书写一个将要使用注解修饰的Java类

由于我们没有具体的使用场景,只能就语法进行讨论,所以简单定义一个Java类如下:

1
2
3
4
5
6
7
public class Student{
public void study(int times){
for(int i = 0; i < times; i++){
System.out.println("Good Good Study, Day Day Up!");
}
}
}

接下来,我们就可以在这个类身上使用我们的LovoAnnotation

我们先分析一下LovoAnnotation的定义:

  1. 注解名叫做LovoAnnotation,因此我们要使用的标记形式应该是:@LovoAnnotation;
  2. LovoAnnotation的@Target是定义为Element.TYPE的,那么它书写的位置应该在类型定义的上方,即:public class Student之上;
  3. 由于我们在LovoAnnotation中定义的有注解类型元素,而且有些元素是没有默认值的,这要求我们在使用的时候必须标记名后面打上(),并且在()内以“元素名=元素值“的形式挨个填上所有没有默认值的注解类型元素(有默认值的也可以填上重新赋值),中间用“,”号分割;

所以我们最终书写的正确形式如下:

1
2
3
4
5
6
7
8
@LovoAnnotation(name="zhang3",age=24,scores={85,67,72})
public class Student{
public void study(int times){
for(int i = 0; i < times; i++){
System.out.println("Good Good Study, Day Day Up!");
}
}
}

特殊语法:
1、如果注解本身没有定义注解类型元素,那么在使用注解的时候可以省略(),直接写为:@注解名,它和标准语法@注解名()等效!
1
2
3
@Target({ElementType.TYPE})
public @interface SpecialAnnotation{
}

1
2
3
4
5
6
7
//等效于@SpecailAnnotation()
@SpecailAnnotation
public class SomeBean{
//属性
//构造
//行为
}

2、如果注解本身在其内部只定义了一个注解类型元素,并且其命名为value,那么在使用注解的时候可以直接写为:@注解名(注解值),它和标准写法:@注解名(value=注解值)等效!
1
2
3
4
@Target({ElementType.TYPE})
public @interface SpecialAnnotation{
float value();
}

1
2
3
4
5
6
7
//等效于@SpecailAnnotation(value=2.26f)
@SpecailAnnotation(2.26f)
public class SomeBean{
//属性
//构造
//行为
}

3、如果注解中某个注解类型元素是一个数组类型,在使用时又出现只需要填入一个值的情况,那么在使用注解的时候可以直接写为:@注解名(类型名=类型值),它和标准写法:@注解名(类型名={类型值})等效!
1
2
3
4
@Target({ElementType.TYPE})
public @interface SpecialAnnotation{
String[] addresses();
}

1
2
3
4
5
6
7
//等效于@SpecailAnnotation(addresses={"NYC"})
@SpecailAnnotation(addresses="NYC")
public class SomeBean{
//属性
//构造
//行为
}

4、如果一个注解的@Target是定义为Element.PARAMETER,那么这个注解是配置在方法的形参前面的,其语法形式如下:
1
2
3
4
@Target({ElementType.PARAMETER})
public @interface SpecialAnnotation{
boolean flag();
}

1
2
3
4
5
6
7
8
public class SomeBean{
//属性
//构造
//行为
public void test(@SpecailAnnotation(flag=true) int num){
//方法实现部分
}
}

5、如果一个注解的@Target是定义为Element.PACKAGE,那么这个注解是配置在package-info.java中的,而不能直接在某个类的package代码上面配置。

最后,我们生成DOC文档

由于我们在定义LovoAnnotation注解的时候,使用了元注解@Documented,所以我们可以在生成的Doc文档中找到Student这个类的描述,并在描述中看到它身上配置的注解信息。
doc文档截图

总结

在我们的日常的使用中,主要执行的操作就是把定义好的注解配置在我们自己写的Java代码上。所以注解的配置语法几乎是我们最频繁的操作。如果我们掌握了本次讲解的内容,就完全不用针对每一个注解去死记硬背它的配置方式,而是可以方便的通过该注解的定义就能推出它的配置语法,也便于我们使用JavaDoc文档去查询学习新的注解。
好吧,在掌握了本次的内容后,我们就可以继续学习如何在运行期得到我们在编写代码时配置的注解内容,请期待本系列的下一节。

系列:
注解Annotation全解析(一):我不是注释
注解Annotation全解析(二):自定义注解的定义
注解Annotation全解析(三):自定义注解的配置使用
注解Annotation全解析(四):自定义注解的运行时解析
注解Annotation全解析(五):注解与XML的比较

坚持原创技术分享,您的支持将鼓励我继续创作!