元注解(meta-annotation)
元注解的作用就是负责注解其他注解。Java5.0定义了4个标准的meta-annotation类型,它们被用来提供对其它 annotation类型作说明。Java5.0定义的元注解有以下几种
@Target
@Retention
@Documented
@Inherited
@Target
@Target说明了Annotation所修饰的对象范围:Annotation可被用于 packages、types(类、接口、枚举、Annotation类型)、类型成员(方法、构造方法、成员变量、枚举值)、方法参数和本地变量(如循环变量、catch参数)。
作用
用于描述注解的使用范围(即:被描述的注解可以用在什么地方)
取值(ElementType)
/**用于描述类、接口(包括注释类型)或枚举声明 */
TYPE
/** 字段声明(包括枚举常量) */
FIELD
/** 用于描述方法 */
METHOD
/** 用于描述参数 */
PARAMETER
/** 用于描述构造器 */
CONSTRUCTOR
/** 用于描述局部变量 */
LOCAL_VARIABLE
/** 注解类型声明 */
ANNOTATION_TYPE
/** 用于描述包 */
PACKAGE
/** 1.8版本开始,描述类、接口或enum参数的声明 */
TYPE_PARAMETER
/** 1.8版本开始,描述一种类、接口或enum的使用声明 */
TYPE_USE
栗子
// 注解@PermissionsAnnotation可用于注解方法
@Target(ElementType.METHOD)
public @interface PermissionsAnnotation {
}
@Target({ElementType.TYPE, ElementType.METHOD, ElementType.PARAMETER})
public @interface TempAspect {
}
@Retention
@Retention定义了该Annotation被保留的时间长短:某些Annotation仅出现在源代码中,而被编译器丢弃;而另一些却被编译在class文件中;编译在class文件中的Annotation可能会被虚拟机忽略,而另一些在class被装载时将被读取(请注意并不影响class的执行,因为Annotation与class在使用上是被分离的)。使用这个meta-Annotation可以对 Annotation的“生命周期”限制。
作用
表示需要在什么级别保存该注释信息,用于描述注解的生命周期(即:被描述的注解在什么范围内有效)
取值(RetentionPoicy)
/** 在源文件中有效(注解将被编译器丢弃) */
SOURCE
/** 在class文件中有效(注解将被编译器记录在类文件中,但不需要在运行时由 VM 保留) */
CLASS
/** 在运行时有效(注解将被编译器记录在类文件中,并在运行时由 VM 保留,因此它们可以被反射读取。)
*/
RUNTIME:
栗子
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface IsInheritedAnnotation {
public String name() default "---";
}
@Documented
@Documented 注解表明这个注解应该被 javadoc工具记录. 默认情况下,javadoc是不包括注解的. 但如果声明注解时指定了 @Documented,则它会被 javadoc 之类的工具处理, 所以注解类型信息也会被包括在生成的文档中,是一个标记注解,没有成员。
@Inherited
@Inherited 元注解是一个标记注解,@Inherited阐述了某个被标注的类型是被继承的。如果一个使用了@Inherited修饰的annotation类型被用于一个class,则这个annotation将被用于该class的子类。
作用
允许子类继承父类的注解
示例
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Inherited
public @interface IsInheritedAnnotation {
public String name() default "---";
}
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface NoInherritedAnnotation {
public String name() default "";
}
@IsInheritedAnnotation
class Super{
private int superPrivateF;
public int superPublicF;
public Super(){
}
private int superPrivateF(){
return 0;
}
public int superPublicF(){
return 0;
}
}
@NoInherritedAnnotation
class Sub extends Super{
private int subPrivateF;
public int subPublicF;
private Sub(){
}
public Sub(int i){
}
private int subPrivateF(){
return 0;
}
public int subPublicF(){
return 0;
}
}
@Test
public void testInheritedAnnotation(){
Class<Sub> clazz = Sub.class;
System.out.println("============================AnnotatedElement===========================");
//注解IsInheritedAnnotation是否存在于元素上
System.out.println(clazz.isAnnotationPresent(IsInheritedAnnotation.class));
//如果存在该元素的指定类型的注释IsInheritedAnnotation,则返回这些注释,否则返回 null。
System.out.println(clazz.getAnnotation(IsInheritedAnnotation.class));
//继承
System.out.println(Arrays.toString(clazz.getAnnotations()));
//自身
System.out.println(Arrays.toString(clazz.getDeclaredAnnotations()));
}
运行结果
true
@com.venom.service.temp.annotation.IsInheritedAnnotation(name=---)
[@com.venom.service.temp.annotation.IsInheritedAnnotation(name=---), @com.venom.service.temp.annotation.NoInherritedAnnotation(name=)]
[@com.venom.service.temp.annotation.NoInherritedAnnotation(name=)]
@Inherited注解说明
类继承关系中@Inherited的作用
类继承关系中,子类会继承父类使用的注解中被@Inherited修饰的注解
接口继承关系中@Inherited的作用
接口继承关系中,子接口不会继承父接口中的任何注解,不管父接口中使用的注解有没有被@Inherited修饰
类实现接口关系中@Inherited的作用
类实现接口时不会继承任何接口中定义的注解