1.注解之什么是注解

注解又叫做注释,Annotation。
注解Annotation是一种引用数据类型,编译之后也是.class文件。
自定义注解的语法:修饰符 @interface 注解类型名{}

例如注解Override,这个注解只能注解方法,这个注解是个编译器参考的,和运行阶段没有关系,凡是java中的方法带有这个注解的,编译器都会进行编译检查,如果这个方法不是重写父类方法,编译器就会报错。

例如注解Deprecated,这个注解表示的元素已过时,可以标注在任何地方,表示使用的元素已过时,有更好的解决方案存在。

元注解
用来标注注解类型的注解称为元注解。常见的元注解有:Target,Retention。

关于Target注解
这是一个元注解,这个Target注解用来标注“被标注的注解”可以出现在那些位置上。

  1. // 表示下面的注解只能出现在方法上
  2. @Target(ElementType.METHOD)
  3. @Retention(RetentionPolicy.SOURCE)
  4. public @interface Override {
  5. }

关于Retention注解
这个元注解Retention用来标注“被标注的注解”最终保存在哪里

  1. @Target(ElementType.METHOD)
  2. // 表示下面的注解文件最终被保存在java源文件中
  3. // Annotations are to be discarded by the compiler.
  4. @Retention(RetentionPolicy.SOURCE)
  5. public @interface Override {
  6. }

RetentionPolicy.SOURCE:该注解只被保存在java源文件中
RetentionPolicy.CLASS:该注解被保存在class文件中。
RetentionPolicy.RUNTIME:该注解被保存在class文件中,并且可以被反射机制操作。

2.注解中的属性

在注解中可以有一个或多个属性,在调用注解时必须要对应地给注解赋值。

  1. @myAnnoation(s = "abc")
  2. public class Test01 {
  3. }
  4. public @interface myAnnoation {
  5. String s();
  6. }

我们可以在定义注解的时候把属性设置为默认值

  1. @myAnnoation()
  2. // 这样的话使用注解中可以不为属性赋值
  3. public class Test01 {
  4. }
  5. public @interface myAnnoation {
  6. int age() default 23;
  7. }

如果注解中的属性值的名称叫value,那么使用注解时可以不写属性名

  1. @myAnnoation(23)
  2. public class Test01 {
  3. }
  4. public @interface myAnnoation {
  5. int value();
  6. }

注解中的属性都有哪些
byte short int long float double boolean char String Class 枚举类型
以及以上每一种的数组形式,如果注解中的属性时数组形式,那么使用注解时参数要用大括号包围起来。

3.学习Retention的源代码、

  1. // 首先Retention自己注解自己,表示最后产生的注解文件方法class文件中并且能被反编译机制获取到
  2. @Retention(RetentionPolicy.RUNTIME)
  3. // 其次规定了这种注解只能用在注解上,是一个元注解
  4. @Target(ElementType.ANNOTATION_TYPE)
  5. public @interface Retention {
  6. // 属性中有一个枚举类型的value
  7. // 使得Retention的属性列表里省略了属性名
  8. RetentionPolicy value();
  9. }
  1. public enum RetentionPolicy {
  2. // 这是Retention注解中所对应的枚举
  3. SOURCE,
  4. CLASS,
  5. RUNTIME
  6. }

4.实际使用

判断类是否被某一个注解标注

  1. package myPackage;
  2. @myAnnoation()
  3. public class Test01 {
  4. public static void main(String[] args) throws Exception {
  5. // 反射就要先获取类
  6. Class c = Class.forName("myPackage.Test01");
  7. // 判断类上面有myAnnotation注解吗
  8. // 注意这个方法的参数不是String类型的
  9. System.out.println(c.isAnnotationPresent(myAnnoation.class));
  10. }
  11. }

注解定义

  1. package myPackage;
  2. import java.lang.annotation.ElementType;
  3. import java.lang.annotation.Retention;
  4. import java.lang.annotation.RetentionPolicy;
  5. import java.lang.annotation.Target;
  6. // 希望这个注解只能用到类上和方法上
  7. @Target({ElementType.TYPE,ElementType.METHOD})
  8. // 希望这个注解能被反射
  9. @Retention(RetentionPolicy.RUNTIME)
  10. public @interface myAnnoation {
  11. }

获取到一个注解

  1. // 注意这里最好加上强制转换
  2. Annotation annotation = (Annotation) c.getAnnotation(myAnnoation.class);
  3. System.out.println(annotation);

获取到注解的一个属性