注解

74 阅读2分钟
章节:
1.概念
2.使用场景 
3.常见的注解
4.自定义注解
5.注解缺点

1.概念

注解:起到标注、注释的作用。本身没有意义,需要结合反射、插住、动态代理等技术使用。


public @interface Test {

}

元注解(meta-annotation):就是注解的注解。 例如: 1.@Documented :注解是否包含在javaDoc中。 2.@Retention(RetentionPolicy.SOURCE) //保留级别,什么时候使用该注解。 3.@Target注解用在什么地方。 4.@Inherited 是否允许子类继承该注解。 ...


@Retention(RetentionPolicy.SOURCE) //保留级别
 
@Target({ElementType.Type}) //作用在哪里,是一个数组:可以在类上、方法、字段等。

@interface Test {

}

Retention / Target 等就是元注解

RetentionPolicy.SOURCE:生成class文件的时候,不带上这个注解。

RetentionPolicy.CLASS; java 生成.class文件保留,但会被jvm抛弃。android 打包dex的时候,不带上这个注解。

RetentionPolicy.RUNTIME;被虚拟机解析识别。

SOURCE < CLASS < RUNTIME。后者包含了前者。

2.使用场景

RUNTIME :会被虚拟机识别。可以结合反射使用。

CLASS:字节码插桩(在class文件写代码)

SOURCE: IntDef

1.APT 在编译时期生成java类。例如在Glide里面会生成一些类。

28283076-a3fe0484a37078b3.png

扩展一下:APT执行时期:

28283076-572c020adf7b722b.png 原理:apt技术其实就是javac的一种,算是一个小插件。

2.IntDef 达到限制参数的取值范围。替换掉枚举的一种方式。 扩展: 枚举在编译后,会把枚举里面的每个值都编译成为对象,更加耗内存。


@Retention(RetentionPolicy.SOURCE)

@IntDef({

Corner.TOP_LEFT, Corner.TOP_RIGHT,

    Corner.BOTTOM_LEFT, Corner.BOTTOM_RIGHT

})

public @interface Corner {

  int TOP_LEFT =0;

  int TOP_RIGHT =1;

  int BOTTOM_RIGHT =2;

  int BOTTOM_LEFT =3;

}

##3.常见的注解 常见的注解:例如:@Override 、@NonNull 、@StringRes等。

@Retention(RetentionPolicy.SOURCE)
@Target({ElementType.METHOD})
public @interface Override {
}
@Documented
@Retention(CLASS)
@Target({METHOD, PARAMETER, FIELD, LOCAL_VARIABLE, ANNOTATION_TYPE, PACKAGE})
public @interface NonNull {
}

##4.自定义注解

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface Test {
    Object name();//错误、注意一下,返回值只能是Enum、八种基本类型、String、Class、annotation和这12种类型的数组。
    String name();
}

注意一下,注解的返回值只能是Enum、八种基本类型、String、Class、annotation和这12种类型的数组。

28283076-7493ca057232a5b5.png

//定义
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD})
public @interface Test {
    String name() default "default_name";//默认值
    String value() default "default_value";
}
//使用
public class User {
    @Test(name = "name1") //这里注意一下。如果是方法不是value、需要用方法名 = '××'
    private String name;

    @Test("name2")
    private String name_2;
}

//利用反射取值
  User user = new User();
  Field[] declaredFields = user.getClass().getDeclaredFields();
  for (Field declaredField : declaredFields) {
     if (declaredField.isAnnotationPresent(Test.class)) {
         Test annotation = declaredField.getAnnotation(Test.class);
         String name = annotation.name();
         String value = annotation.value();
          Log.e("TAG", "value =" + value + ",name=" + name);
         }
   }


输出:
value =name2,name=default_name
value =default_value,name=name1

##5.注解缺点 1.分散在java各个文件中。不好管理。