Java注解Annotation 简单总结及应用

112 阅读3分钟

又称Java标注,是一种注释机制。注解是元数据的一种形式,为代码添加一些额外信息。使用关键字@interface定义。

1. 元注解

  - 定义:对注解类型进行注解的注解类。一般在定义注解类型时,需要指定的元注解有两个:`@Target``@Retention`。另外还有`@Documented``@Inherited`  - `@Target`:定义Annotation所修饰的对象类型
    - ElementType.ANNOTATION_TYPE 可以应用于注解类型。
    - ElementType.CONSTRUCTOR 可以应用于构造函数。
    - ElementType.FIELD 可以应用于字段或属性。
    - ElementType.LOCAL_VARIABLE 可以应用于局部变量。
    - ElementType.METHOD 可以应用于方法级注解。
    - ElementType.PACKAGE 可以应用于包声明。
    - ElementType.PARAMETER 可以应用于方法的参数。
    - ElementType.TYPE 可以应用于类的任何元素。
    
  - `@Retention` 指定注解的生命周期
    - RetentionPolicy.SOURCE - 仅保留在源级别中,当Java文件编译成class文件时,注解被遗弃。可用于IDE代码语法检查、APT等。
    - RetentionPolicy.CLASS - 在编译时由编译器保留在class文件中,但 Java 虚拟机(JVM)会忽略。应用于字节码操作,如AspectJ、热修复Roubust等。
    - RetentionPolicy.RUNTIME - 标记的注解由 JVM 保留,因此运行时结合反射技术获取注解中的所有信息。比如早期的ButterKnife方案。

2. 应用实例

2.1 IDE代码语法检查应用实例

使用整型静态变量替换枚举类。编译器会为Enum类中每一项创建一个对象实例,赋值给我们定义枚举类型常量,并声明枚举对象数组来保存所有的枚举对象。每个整型静态变量占内存4字节,而枚举对象占用的内存:对象头(12)+对象引用(name,4)+索引(ordinal,4),除此之外还有数组,所以内存占用远大于静态变量。

结合@IntDef自定义注解,减少内存占用。

  @IntDef(value = {Demo.TYPE1, Demo.TYPE2})
  @Target(ElementType.PARAMETER)
  @Retention(RetentionPolicy.SOURCE)
  public @interface IType {
  }
public final class Demo {
    public static final int TYPE1 = 1;
    public static final int TYPE2 = 2;
    private void setType(@IType int type) {
    ````
    }
  }

2.2 APT

APT:“annotation processor tool”,注解处理器,用于处理注解。编写好的java源代码,经过javac的编译,变成jvm能够加载解析的字节码class文件。javac本身就自带apt,用来在编译器扫描处理注解信息。当然也可以为某些注解注册自己的注解处理器,注册的apt由javac调起,并将注解信息传递给注册的apt。在glide、butterknife、arouter、eventbus中都有应用。不过这些框架的注解大都是class级别。

推荐一个Java插件Lombok,可以自动实现数据bean的get、set、toString等方法。 原理也是使用apt。

参考ButterKnife源码,自己写一个,文章链接使用自定义注解自己实现ButterKnife功能 - 掘金 (juejin.cn)

2.3 字节码操作

直接修改字节码class文件,来达到修改代码执行逻辑的目的。比如运行期权限判定、代码中多次需要进行是否登陆的判断等。

字节码操作框架的作用在于生成或者修改Class文件,在Android中字节码框架本身是不需要打包进入APK的, 只有其生成/修改之后的Class才需要打包进入APK中。它的工作时机在Android打包流程中的生成Class之后, 打包dex之前。常见的字节码操作框架是ASMAspectJ就是通过ASM实现的。

ASM 可以直接从jcenter()仓库中引入 implementation "org.ow2.asm:asm:9.4"

实例todo