注解(Annotation),也叫元数据。一种代码级别的说明。它是JDK1.5及以后版本引入的一个特性,与类、接口、枚举是在同一个层次。它可以声明在包、类、字段、方法、局部变量、方法参数等的前面
作用分类:
1)编写文档:通过代码里标识的元数据生成文档【生成文档doc文档】
2)代码分析:通过代码里标识的元数据对代码进行分析【使用反射】
3)编译检查:通过代码里标识的元数据让编译器能够实现基本的编译检查【Override】
包含的JDK基本内置注解(编译检查):
@Override :标记当前该方法是否继承父类或者是实现接口的抽象方法!
@Deprecated :标记某个类的成员方法是否已经过时了
@SuppressWarnings:压制警告(方法上/或类上),解决类中的所有黄色警告线!
@FunctionalInterface:函数式接口,标记当前这个接口只有一个抽象方法!
高级注解:
@Target:当前该接口作用位置:标记在类上 TYPE,标记在方法METHOD,FIELD(成员变量上)
其他的元注解
@Documented:将当前注解中的属性的文档注释抽取都api中
@Target:标记当前自定义注解/jdk内置注解能够使用操作的范围
value属性的返回值:ElementType[] 枚举数组
public enum ElementType {
TYPE, 将当前这个注解标记类上
FIELD, 将当前注解标记在成员变量
METHOD,标记成员方法上
}
@Retention:标记当前自定义注解的保留阶段
RetentionPolicy value();
RetentionPolicy:枚举
SOURCE,Java源代码(编译)
CLASS,(产生字节码文件:需要通过反射加载类中的成员:Constructor,Field,Method)
RUNTIME;(运行阶段) :考虑这个阶段!(开发者使用)
@Inherited :标记当前这个注解,可以被子类继承!
如何解析一个自定义注解呢?
1)在哪个类中使用的这个注解,获取该类的字节码文件对象
2)通过该类的字节码文件对象加载这个注解
Class类中:字节码文件对象
public <A extends Annotation> A getAnnotation(Class<A> annotationClass)
获取到了注解对象----->相当于获取到了接口的子实现类对象了
3)调用该返回的注解(接口)的子实现类对象的属性
4)创建Properties属性集合类
5)通过反射获取
//自定义一个注解
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.TYPE) //将@MyProperties标记在类上使用
@Retention(RetentionPolicy.RUNTIME) //保留在运行阶段
public @interface MyProperties
String className() ;
String methodName() ;
}
public class Student {
public void love() {
System.out.println("爱学习...");
}
}
public class Teacher {
public void love() {
System.out.println("爱Java...");
}
}
import java.lang.reflect.Method;
@MyProperties(className = "com.cn.Student",methodName="love")
public class Test {
public static void main(String[] args) throws Exception {
//获取该类Test字节码文件对象
Class<Test> clazz = Test.class ;
//通过该类的字节码文件对象加载这个注解
MyProperties myPro = clazz.getAnnotation(MyProperties.class) ;
/*
* 相当于: public interface MyProperties{
* String className()
* String methodName()
* }
* */
String className = myPro.className() ;
String methodName = myPro.methodName() ;//love方法名
//创建属性集合类对象
Class<?> c = Class.forName(className) ;
//直接通过字节码文件对象获取该类实例
Object obj = c.newInstance() ;//Student类的实例
//获取Method对象
Method m = c.getMethod(methodName) ;
//调用
m.invoke(obj) ;
}
}