package annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.lang.reflect.Method;
import org.junit.Test;
/*(1)注解使用范围:类上,方法上,构造方法,属性上,,局部变量上,参数上,包名上(除了调用的方法上)
* (2)定义注解属性:
* 格式:@interface 注解名称{
* int age();//这是属性,不是方法就是这么定义的
* String name();//同上
* }
* 注解属性可以定义默认值:int age() default 12;
* (3)注解的使用:
* 1.要给属性赋值,格式:@注解名(age=12,name="李四")
* 2.特殊的value属性,在只有这一个属性的时候可以不用写value属性名,直接写值,格式:@注解名(100);
* (4)注解属性类型:
* 1.8种基本数据类型
* 2.String类型
* 3.Class类型
* 4.enum类型
* 5.注解类型
* 6.以上类型的一维数组:int[],当只有一个元素时可以省去{}
* (5)注解范围的限定:指定使用目标
* 用到注解@Target(ElementType[]),ElementType是枚举类型
* 格式:@Target(value={ElementType.。。。。。},。。。),当value只有一个值时可省略为:@Target(ElementType.。。。)
* (6)注解保留策略
* 1.源代码(SOURCE):保留在编译时的Java文件中,不保留到字节码文件(擦除)
* 2.字节码(CLASS):保留到编译时的Java和class文件中,不保留到内存中(jvm加载会擦除)
* 3.jvm(RUNTIME):保留到编译时的Java和class文件以及内存中,唯一可以进行反射注解
* (7)限定注解的保留策略
* @Retention(RententionPolicy.。。。),RententionPolicy是枚举类型(枚举选项:SOURCE,CLASS,RUNTIME)
*/
//属性类型演示
@interface MyAnnot1 {
int a();
String b();
Class c();
Enum d();
int[] e();
MyAnnot2 f();
}
//定义枚举类
enum Enum {
a, b, c
}
@Target(ElementType.ANNOTATION_TYPE)
@interface MyAnnot2 {
}
/*
* 注解的反射: 1.获取注解目标对象 2.获取目标对象上的的注解类型 3.通过类型反射
*/
@MyAnnot1(a = 12, b = "", c = String.class, d = Enum.a, e = {}, // 不能new,只能{}
f = @MyAnnot2())
public class MyAnnotation {
final String c = "12";
@Test
public void fun1() throws NoSuchMethodException {
// 获取注解目标对象
Method fun2 = this.getClass().getMethod("fun2");
// 获取目标对象上的注解类型
AnnotationReflect reflect = fun2.getAnnotation(AnnotationReflect.class);
// 反射操作注解的属性等
String string = reflect.str();
System.out.println(string);
}
@AnnotationReflect(str = "我是注解反射")
public void fun2() {
}
}
@Retention(RetentionPolicy.RUNTIME) // 注解的反射必须要进行保留策略的限定,否者会被擦除,无法使用反射
@Target(ElementType.METHOD) // 限定注解使用范围为方法上
@interface AnnotationReflect {
String str();
}
重点:
通过注解反射可以获取注解属性的所有内容,加上获取注解的目标对象就可以对目标对象进行各种操作,比如:注解创建对象、单元测试配置文件的加载等等。