1.自定义注解
注解本质上就是一个接口,该接口默认继承Annotation接口。
public interface MyAnno extends java.lang.annotation.Annotation{}
注解的格式:
public @interface 注解名称{
// 定义体
}
2.元注解(描述注解的注解)
@Target注解:描述注解能够作用的位置
TYPE:可以作用于类上。
METHOD:可以作用于方法上。
FIELD:可以作用于成员变量上。
CONSTRUCTOR:可以作用于构造器上。
PARAMETER:可以作用于方法的形参上。
@Retention注解:描述被保留的阶段
@Retention(RetentionPolicy.SOURCE) :当前被描述的注解,不会保留到class字节码文件中,并不被JVM读取到。
@Retention(RetentionPolicy.CLASS) :当前被描述的注解,会保留到class字节码文件中,但不会被JVM读取到。
@Retention(RetentionPolicy.RUNTIME) :当前被描述的注解,会保留到class字节码文件中,并被JVM读取到。
@Documented注解:描述注解是否被抽取到API文档中
@Inherited注解:描述注解是否被子类继承
@Target({ElementType.TYPE,ElementType.METHOD,ElementType.FIELD}
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
public @interface AnnoTest {
}
3.注解的属性(类似于接口中的抽象方法)
1.属性的返回值类型:基本数据类型、String类型、Class类型、枚举类型、注解类型、以上所有类型的数组。
2.定义了属性,在使用的时需要给属性赋值。如果定义属性时,使用default关键字给属性默认初始化值,使用注解时可以不进行赋值。只有一个属性需要赋值,并且属性的名称是value,则value可以省略直接定义值即可。数组赋值时使用{}包裹,如果数组中只有一个值,则{}可以省略。
public @interface Anno1 {
//返回值:基本数据类型
int value();
//返回值:String
String showString() default "null~";
//返回值:枚举
EnumDemo showEnum();
//返回值:注解
AnnoDemo showAnno();
// 返回值:数组
int[] showIntArray();
}
4.案例
4.1 定义注解类
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface AnnoTest {
// 描述需要执行的类名和方法名
String className();
String methodName();
}
4.2 编写一个普通类
public class ClassTest{
public void input(){
System.out.println("ClassTest....input()...执行了....");
}
}
4.3 测试
@AnnoTest(className ="com.obtk.annotation.ClassTest",methodName ="input")
public classAnnoDemoTest {
public static void main(String[] args) throwsException {
//1.获取该类的字节码文件对象
Class<AnnoDemoTest> testClass = AnnoDemoTest.class;
//2.获取上边的注解对象
AnnoTest annotation = testClass.getAnnotation(AnnoTest.class);
//3.调用注解对象中定义的抽象对象方法,获取返回值
String className = annotation.className();
String methodName = annotation.methodName();
//3.加载该类进内存
Class cls = Class.forName(className);
//4.创建对象
Object obj = cls.newInstance();
//5.获取方法对象
Method method = cls.getMethod(methodName);
//6.执行方法
method.invoke(obj);
}
}