Java注解

注解定义

Java 注解(Annotation)又称 Java 标注,是 JDK5.0 引入的一种注释机制。 其实注解本身对他们注解的代码并没有直接影响,仅仅像一个段"注释"一样。

注解的创建与简单使用

创建一个注解,如上,创建一个注解,跟我们创建一个类对比:
public @interface Test {
    String str();
    int num();
}

public class A {
    String string;
    int number;
}
  • 创建注解的关键字是@interface,创建类的关键字是class
  • 注解声明一个String类型成员变量方式:String str();,而类声明一个String类型成员变量方式:String string;
使用注解:
public @interface Test {
    String str() default "sss";//可以给这个成员指定一个默认值
    int num();
}

public class A {
    @Test(num = 0)
    String string;
    @Test(str = "",num = 1)
    int number;
}

  • 看下A类中的成员变量string和int都使用了Test注解,这个注解有两个参数,在使用时需要我们以key-value形式传入,如果注解给了default值,也可以不用传
public @interface Test {
    String value();
}

public class A {
    @Test("xxx")
    String string;
}
  • 当只有一个参数时,并且声明为value时,就比较特殊,使用时可以直接@Test("xxx")这样使用。当然一个注解也可以没有参数。
到此为止,以上自己写的注解,还没有任何作用,仅仅像注释一样标在了类中的成员变量上而已,对我们的代码程序还没有丝毫影响,如果想要影响我们的代码,还需要对这些类似注释一样的东西在恰当的时机进行"解读"。

元注解

先了解下什么是元注解:在定义注解时,注解类也能够使用其他的注解声明。作用在注解类型上的注解,我们称之为 元注解。

  • @Documented:将被此注解注释的注解包含在 javadoc 中 ,它代表着这个注解会被javadoc工具提取成文档。

  • @Inherited:表示允许子类继承父类中定义的注解

  • @Retention:表示在什么级别保存该注解信息,可选参数在RetentionPolicy枚举中,它是我们在自定义注解中比较常用的元注解。

    • @Retention(RetentionPolicy.SOURCE) 源码级别,保留在源码阶段,会被编译器忽略。看下使用场景:

      • 可给APT使用,在java文件通过javac编译生成.class文件时,javac通过注解处理器可以采集到源码中注解信息,打包到Element中,在注解处理程序(AbstractProcessor的process())中处理解析注解,(在编译期间,注解处理程序由javac调起,先执行注解处理程序,再将java文件编译成class)。其主要用于生成一些辅助类文件。注解处理器对注解的应用有很多,如Glide,EventBus3,Butterknife。

      • IDE语法检查,如使用IndDef注解的注解,可以在IDE中编辑代码时限定我们的入参类型,用于替代枚举。如以下调用addPeople时对入参类型限制为0或者1

        public static final int WOMAN = 0;
        public static final int MAN = 1;
        @IntDef(value = {MAN,WOMAN})
        @Retention(RetentionPolicy.SOURCE)
        @Target(ElementType.PARAMETER)
        public @interface People{
        }
        
        
        public void addPeople(@People int people) {
        }
        
    • RetentionPolicy.CLASS,字节码级别,注解在编译时由编译器保留在class文件中,但Java虚拟机会忽略(即无法在运行期反射获取注解)。如:字节码增强(插桩),在字节码中写代码(class文件有自己的数据结构,主要有无符号数和表组成)

    • RetentionPolicy.RUNTIME,运行时,标记的注解由JVM保留,因此运行时环境可以使用它,在程序运行期间,通过反射技术动态获取注解与其元素,如通过注解和反射简单粗暴的实现findViewById功能:

      @Retention(RetentionPolicy.RUNTIME)
      @Target(ElementType.FIELD)
      public @interface InjectView {
          int value();
      }
      public class Inject {
          public static void inject(Activity activity){
                  //获取activity的Class对象
              Class aClass = activity.getClass();
              //获取所有的成员变量
              Field[] fields = aClass.getDeclaredFields();
              for (Field field : fields) {
                      //判断是否被InjectView注解
                  boolean annotationPresent = field.isAnnotationPresent(InjectView.class);
                  if (annotationPresent) {
                      field.setAccessible(true);
                      //获取注解以及其属性值
                      InjectView annotation = field.getAnnotation(InjectView.class);
                      int value = annotation.value();
                      try {
                              //进行findViewById操作
                          View view = activity.findViewById(value);
                          //给view成员变量设置值
                          field.set(activity,view);
                      } catch (Exception e) {
                          e.printStackTrace();
                      }
                  }
      
              }
          }
      }
      public class MainActivity extends AppCompatActivity {
          @InjectView(R.id.button)
          TextView textView;
          @Override
          protected void onCreate(Bundle savedInstanceState) {
              super.onCreate(savedInstanceState);
              setContentView(R.layout.activity_main);
              Inject.inject(this);
              textView.setText("通过注解和反射findViewById");
          }
      }
      

你可能感兴趣的:(Java注解)