一.注解
-
Java5开始,java开始对元数据的支持,也就是Annotation(注解)。
-
所有的Annotation都是java.lang.annotation.Annotation 接口的子接口,所以Annotation是一种特殊的接口(枚举也是特殊的类);
@interface Override {} ---> interface Override extends java.lang.annotation.Annotation{}
使用注解需要注意,必须有三方参与才有意义:
- :得有注解标签本身;
- :被贴的程序元素(类,字段,构造器,方法,参数上,包上等);
- :由第三方的程序使用反射的手段来赋予注解特殊的功能(也是Java代码).
二.元注解
-
注解:用来贴在类/方法/变量等之上的一个标记,第三方程序可以通过这个标记赋予一定功能
-
元注解:在定义注解的时候用来贴在注解上的注解,用来限定注解的用法
-
元注解有4个:
@Retention、@Target、@Documented、@Inherited
@Documented 表示注解会被javadoc指令编辑到API中
@Inherited 表示注解会遗传给子类
@Retention:决定注解可以保存到哪个时期
注解的有效期有3个都封装在枚举:RetentionPolicy中
RetentionPolicy.SOURCE: 表示注解只存在于源文件中,不会被编译到字节码中
RetentionPolicy.CLASS: 表示注解会被编译到字节码中,但是JVM不加载注解
RetentionPolicy.RUNTIME: 表示注解会被编译到字节中,会随着字节码的加载而进入JVM,因此可以反射性地读取(重)
不指定时,默认是RetentionPolicy.CLASS
@Target:决定了该注解可以贴在什么地方
可以贴注解的地方有很多,都封装在枚举:ElementType中
ElementType.TYPE 贴在类、接口或枚举上(重)
ElementType.METHOD 贴在方法上(重)
ElementType.FIELD 贴在字段上(包括枚举常量,重)
ElementType.ANNOTATION_TYPE 贴在注解上
ElementType.CONSTRUCTOR 贴在构造方法上
ElementType.LOCAL_VARIABLE 贴在局部变量上
ElementType.PACKAGE 贴在包上(极少使用)
ElementType.PARAMETER 贴在参数上
三.注解的定义和使用
定义注解的语法:使用@interface 注解名称
public @interface VIP {
//抽象方法 属性
}
//注解VIP
@Retention(RetentionPolicy.RUNTIME)//保留到运行时刻
@Target(ElementType.TYPE)//可以贴在类上
public @interface VIP {
/**
* 属性的返回值类型只能是
* 基本类型/枚举/Class/注解/String/枚举以及他们各自的一维数组
*/
//Integer age1();//编译错误
int age() default 17;//有一个int类型的参数,默认17
String name();//一个String类型的参数
Gender gender();//枚举
}
使用注解语法:
@注解名[(属性名=属性值,属性名=属性值)]
@VIP(name = "你好", age = 18, gender = Gender.MAN)
public class Person {
// 只能贴在类上
// @VIP(name="你好", age=18, gender=Gender.MAN)
int age;
}
注意:给属性赋值时如果只有1个属性要赋值且名称叫value时,可以省略value不写 如:@VIP(“xxx”)
注意:属性的返回值类型只能是基本类型/枚举/Class/注解/String/枚举以及他们各自的一维数组
四.反射注解
思路:
- :获取注解所在类的字节码对象
- :在字节码中获取出注解对象
- :调用抽象方法获取注解属性的值
常用API:
Annotation[] getAnnotations() 获取目标对象上所有的注解
Annotation A getAnnotation(Class<A> annotationClass) 获取目标对象上的注解,没有则返回null
boolean isAnnotationPresent(Class<? extends Annotation> annotationClass) 判断对象上是否有某种类型的注解
//获取注解
public class AnnoDemo {
public static void main(String[] args) throws Exception {
//1)获取字节码
Class clz = Class.forName("com.huangkun._02_anno.Person");
//获取所有的注解对象 运行时期的 @Retention(RetentionPolicy.RUNTIME)
Annotation[] anno = clz.getAnnotations();
for (Annotation annotation : anno) {
System.out.println(annotation);
}
//2)获取注解对象
VIP vip = (VIP) clz.getAnnotation(VIP.class);
System.out.println(vip);
//3)获取注解属性
System.out.println(vip.name());
System.out.println(vip.age());
System.out.println(vip.gender());
//4)根据属性添加新功能
if (vip.age() > 18) {
System.out.println("请进");
}else
System.out.println("禁止进入");
}
}