一、注解基本概念
- 注解的概念
Java提供了一种和源程序中的元素关联的任何信息和任何元数据的方法和渠道 - 源程序
Java文件 - 元素
构造方法/成员方法/成员变量/访问权限修饰符/注解…
二、Java中常见的注解
- @Override: 表示必须对方法重写
- @Deprecated : 表示方法过时
- @SuppresWarning : 表示忽略警告
- @FunctionalInterface : 表示函数式接口
三、注解的分类
- 按运行机制分类:
- 源码注解: 注解只在源码中存在,当编译生成.class文件的时候,就不存在了
- 编译时注解: 注解在源码和.class文件中存在,当程序运行的时候它就不存在了
- 运行时注解: 在运行的时候还能够起作用的注解,它会动态影响到程序执行逻辑
- 元注解: 对注解进行注解
- 按照来源分类
- JDK自带的注解
- 自定义注解: @Column
- 元注解
四、注解的语法
- 使用@interface关键字来定义注解
- 成员是以没有参数和没有异常的方式声明
- 可以使用default为成员指定一个默认值
- 注解的成员类型可以是很多种
- 如果注解只有一个成员,则成员的命名必须叫做value,再使用这个注解的时候可以不写等于号
- 没有任何成员的注解叫做标识注解,它本身的存在与否就是一种意义,类似于注释
五、元注解
- @Target:标识它所标识的注解能够作用在什么元素上,如果一个注解的@Target上面的注解范围显示了ANNOTATION_TYPE,那么表示该注解是元注解。
- @Retention: 表示它所标识的注解的生命周期
- RetentionPolicy.SOURCE:表示该注解只在源码中存在
- RetentionPolicy.CLASS: 表示该注解只在源码和编译时存在
- RetentionPolicy.RUNTIME: 表示该注解在源码和编译时以及运行时存在
- @Inherited: 表示该注解可以被继承
- @Document: 表示该注解可以在生成API文档的时候显示在文档上
六、通过反射解析注解
-
通过反射可以获取到字节码文件对象,通过字节码文件对象就能够获取到所有的有关该类的元素,然后注解也是类元素的一种,所以可以获取到对应的注解,但是这个注解必须运行时注解。
-
`public class AnnotationDemo01 {
public static void main(String[] args) throws ClassNotFoundException {
Class<?> c = Class.forName(“com.sxt.annotationdemo02.Student”);// 判断该字节码文件中是否存在@MyAnnotation注解 boolean isAnnotationPresent = c.isAnnotationPresent(MyAnnotation.class); if (isAnnotationPresent) { MyAnnotation annotation = c.getDeclaredAnnotation(MyAnnotation.class); System.out.println(annotation.value()); } System.out.println("----------成员方法-------------"); Method[] methods = c.getMethods(); for (Method m : methods) { boolean present = m.isAnnotationPresent(MyAnnotation.class); if (present) { MyAnnotation declaredAnnotation = m.getDeclaredAnnotation(MyAnnotation.class); System.out.println(declaredAnnotation.value()); } } System.out.println("---------构造方法--------------"); Constructor<?>[] constructors = c.getConstructors(); for (Constructor<?> constructor : constructors) { boolean present = constructor.isAnnotationPresent(MyAnnotation.class); if (present) { MyAnnotation declaredAnnotation = constructor.getDeclaredAnnotation(MyAnnotation.class); System.out.println(declaredAnnotation.value()); } } System.out.println("---------成员变量--------------"); Field[] fields = c.getDeclaredFields(); for (Field field : fields) { boolean present = field.isAnnotationPresent(MyAnnotation.class); if (present) { MyAnnotation declaredAnnotation = field.getDeclaredAnnotation(MyAnnotation.class); System.out.println(declaredAnnotation.value()); } } System.out.println("---------toString--------------"); System.out.println("获取tostring方法"); boolean annotationPresent = c.isAnnotationPresent(Override.class); if (annotationPresent) { MyAnnotation annotation = c.getDeclaredAnnotation(MyAnnotation.class); System.out.println(annotation.value()); } System.out.println("---------获取PrimaryStudent上的注解--------------"); Class<?> c2 = Class.forName("com.sxt.annotationdemo02.PrimaryStudent"); boolean result = c2.isAnnotationPresent(MyAnnotation.class); System.out.println(result);
}
}
@MyAnnotation("T_STU")
class Student{
@MyAnnotation("NAME")
private String name;
@MyAnnotation("AGE")
private int age;
@MyAnnotation("STU")
public Student() {
super();
}
public Student(String name, int age) {
super();
this.name = name;
this.age = age;
}
@MyAnnotation("getName")
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
@MyAnnotation("setAge")
public void setAge(int age) {
this.age = age;
}
@MyAnnotation("I'm a toString method")
@Override
public String toString() {
return "Student [name=" + name + ", age=" + age + "]";
}
}
class PrimaryStudent extends Student{
}
@Inherited
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE,ElementType.FIELD,ElementType.METHOD,ElementType.CONSTRUCTOR})
@interface MyAnnotation{
String value();
}
`