14.3.4 Java8新增的重复注解
14.3.4 Java8新增的重复注解
在Java8
以前,同一个程序元素前最多只能使用一个相同类型的注解;如果需要在同一个元素前使用多个相同类型的注解,则必须使用注解“容器”。例如在Struts2
开发中,有时需要在Action
类上使用多个@Result
注解。在Java8
以前只能写成如下形式:
1 |
|
上面代码中使用了两个@Result
注解,但由于传统Java
语法不允许多次使用@Result
修饰同一个类,因此程序必须使用@Results
注解作为两个@Result
的容器,@Results
注解包含一个类型为Result[]
的成员变量value
,程序指定的多个@Result
将作为@Results
的value
属性(数组类型)的数组元素
从Java8
开始,上面语法可以得到简化:Java8
允许使用多个相同类型的注解来修饰同一个类,因此上面代码可能(之所以说可能,是因为重复注解还需要对原来的注解进行改造)可以简化为如下形式:
1 | , |
开发重复注解需要使用@Repeatable
修饰,下面通过示例来示范如何开发重复注解。首先定义一个FKTag
注解。
1 | import java.lang.annotation.*; |
上面定义了FKTag
注解,该注解包含两个成员变量。但该注解默认不能作为重复注解使用,如果使用两个以上的该注解修饰同一个类,编译器会报错。
为了将该注解改造成重复注解,需要使用@Repeatable
修饰该注解,使用@Repeatable
时必须为value
成员变量指定值,该成员变量的值应该是一个“容器”注解——该“容器”注解可包含多个@FkTag
,因此还需要定义如下的“容器”注解
1 | import java.lang.annotation.*; |
上面代码中,定义了一个FkTag[]
类型的value
成员变量,这意味着@FKTags
注解的value
成员变量可接受多个@FkTag
注解,因此@FkTags
注解可作为@FkTag
的容器
修饰@FkTags
注解的的注解:
1 |
指定@FKTags
注解信息也可保留到运行时,这是必需的,因为:@FKTag
注解信息需要保留到运行时,如果@FKTags
注解只能保留到源代码级别(RetentionPolicy.SOURCE
)或类文件(RetentionPolicy.CLASS
),将会导致@FKTags
的保留期小于@FkTag
的保留期,如果程序将多个@FkTag
注解放入@FkTags
中,若JVM
丢弃了@FKTags
注解,自然也就丢弃了@FKTags
的信息——而我们希望@FKTags
注解可以保留到运行时,这就矛盾了。
容器注解保留期要更长
“容器”注解的保留期必须比它所包含的注解的保留期更长,否则编译器会报错
接下来程序可在定义@FkTag
注解时添加如下修饰代码:
1 | ; |
经过上面步骤,就成功地定义了一个重复注解:@FkTag
。读者可能已经发现,实际上@FkTag
依然有“容器”注解,因此依然可用传统代码来使用该注解:
1 |
又由于@FKTag
是重复注解,因此可直接使用两个@FKTag
注解,如下代码所示
1 | , |
实际上,第二种用法只是一个简化写法,系统依然将两个@FkTag
注解作为@FkTags
的value
成员变量的数组元素。
程序 容器注解的本质
如下程序演示了重复注解的本质。
1 |
|
上面程序中的
1 | FkTag[] tags = clazz.getDeclaredAnnotationsByType(FkTag.class); |
这行代码,获取修饰FkTagTest
类的多个@FkTag
注解,此行代码使用的是Java8
新增的getDeclaredAnnotationsByType()
方法,该方法的功能与传统的getDeclaredAnnotation(()
方法相同,只不过getDeclaredAnnotationsByType()
方法相当于功能增强版,它可以获取多个重复注解,而getDeclaredAnnotation()
方法则只能获取一个(在Java8
以前,不允许出现重复注解)
上面程序中的
1 | FkTags container = clazz.getDeclaredAnnotation(FkTags.class); |
这行代码尝试获取修饰FkTagTest
类的@ FkTags
注解,虽然上面源代码中并未显式使用@FKTags
注解,但由于程序使用了两个@FkTag
注解修饰该类,因此系统会自动将两个@FKTag
注解作为@FKTags
的value
成员变量的数组元素处理。
因此,第二行粗体字代码将可以成功地获取到@FkTags
注解。
编译、运行程序,可以看到如下输出:
1 | PS G:\Desktop\随书源码\疯狂Java讲义(第4版)光盘\codes\14\14.3> java FkTagTest |
重复注解只是一种简化写法
重复注解只是一种简化写法,这种简化写法是一种假象:多个重复注解其实会被作为“容器”注解的value
成员变量的数组元素。例如上面的重复的@FkTag
注解其实会被作为@ ,FkTags
注解的value
成员变量的数组元素处理,