元注解
什么是元注解
元注解:即在Java语言中用于修饰自定义注解的一种注解,有@Target、@Retention 、@Documented、@Inherited和@Repeatable常用元注解,其中@Repeatable 是JDK8.0新添加的元注解:
元注解@Target
元注解@Target:用于指定被修饰的自定义注解只能用于修饰程序中哪些元素,该元注解有如下属性值:
1、ElementType.ANNOTATION_TYPE:应用于其他注解的元注解
2、ElementType.CONSTRUCTOR:应用于构造函数
3、ElementType.FIELD:应用于全局属性
4、ElementType.LOCAL_VARIABLE:应用于方法中的本地变量
5、ElementType.METHOD:应用于方法
6、ElementType.PACKAGE:应用于包
7、ElementType.PARAMETER:应用于方法的参数
8、ElementType.TYPE:应用于类、接口或者枚举声明
☆☆加粗内容为常用类型,在下面内容当中会展现出来。
首先我们创建一个Test类,代码如下:
package 元注解;
@Autowried
public class Test {
@Autowried
private String name;
@Autowried
public static void main(@Autowried String[] args) {
}
}
我们可以看出自定义注解Autowried所处的位置比较随意,但是一旦加入@Target注解后,就会发生其他的变化,Autowried代码如下:
package 元注解;
import java.lang.annotation.ElementType;
import java.lang.annotation.Target;
@Target(ElementType.FIELD)
public @interface Autowried {
}
此时在Test类中会出现报错,只有private String name;
不出现报错,由此对应上述情况。
而当@Target元注解中的属性出现多个时,也是需要使用大括号将所有属性包裹。
代码如下:
package 元注解;
import java.lang.annotation.ElementType;
import java.lang.annotation.Target;
@Target({ElementType.FIELD,ElementType.METHOD,ElementType.TYPE,ElementType.PARAMETER})
public @interface Autowried {
}
此时Test类中不出现报错:
元注解@Retention
元注解@Retention:用于指定被修饰的自定义注解可以保留多久,即设置生命时长。该元注解有如下属性值:
1、RetentionPolicy.SOURCE(源码类级别):编译器将直接丢弃被修饰的注解。
2、RetentionPolicy.CLASS(类级别):默认值,编译器将把注解记录在class文件中,当运行Java程序时,虚拟机不再保留注解;
3、RetentionPolicy.RUNTIME(运行时级别):编译器将把注解记录在class文件中,当运行java程序时,虚拟机保留注解,程序可以通过反射获取该注解;
覆盖广度级别由上到下一次递增。
下面根据代码来解释:
在此,先选择级别最高的RetentionPolicy.RUNTIME注解,Autowried中代码展示为:
package 元注解;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target({ElementType.FIELD,ElementType.METHOD,ElementType.TYPE,ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
public @interface Autowried {
}
Test类中代码展示为:
package 元注解;
import java.lang.reflect.Field;
@Autowried
public class Test {
@Autowried
private String name;
@Autowried
public static void main(@Autowried String[] args) {
Class clazz = Test.class;
try {
Field field = clazz.getDeclaredField("name");
Autowried autowried = field.getAnnotation(Autowried.class);
System.out.println(autowried);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
结果显示为:
修改Autowried类中的@Retention中的属性,@Retention(RetentionPolicy.CLASS)
,再次运行代码,结果显示为:
由此结果来说明覆盖广度的优先级。
元注解@Documented
自定义注解一旦被元注解@Documented修饰,在生成doc文档时,类中凡是添加自定义注解,会生成至doc文件当中。
在没有使用元注解@Documented时,结果如图所示:
使用元注解@Documented之后,会出现以国际化形式出现的自定义注解。
元注解@Inherited
元注解@Inherited:如果父类所使用的注解有@Inherited修饰,则子类可以继承该注解,否则不能继承。
因此我们需要创建一对有继承关系的类:
Father类代码如下:
package 元注解;
@Autowried
public class Father {
}
Son类代码如下:
package 元注解;
public class Son extends Father {
}
Test类代码如下:
package 元注解;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
public class Test {
public static void main( String[] args) {
Class clazz = Son.class;
Annotation annotation = clazz.getAnnotation(Autowried.class);
System.out.println(annotation);
}
}
Autowried类代码如下:
package 元注解;
import java.lang.annotation.Inherited;
@Inherited
public @interface Autowried {
}
运行程序,结果为:
出现null的原因,是由于缺少元注解@Retention中的属性(RetentionPolicy.RUNTIME)未能作用于运行时级别,因此无法将正确结果显示出来,修改代码后:
Autowried类代码:
package 元注解;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@Inherited
@Retention(RetentionPolicy.RUNTIME)
public @interface Autowried {
}
结果显示为: