天师

天下事有难易乎?为之,则难者亦易矣;不为,则易者亦难矣。


  • 首页

  • 分类

  • 归档

  • 标签

  • 关于

注解笔记

发表于 2019-08-01 分类于 随手记
本文字数: 3.6k 阅读时长 ≈ 3 分钟
为什么会有本篇文章?

现在很多主流库都是通过APT(Annotation Processing Tool 简称注解处理工具)在代码编译时期,通过解析注解,并且生成新能Java文件,减少开发者手动书写代码,极大的提升了开发效率。

本篇在学习APT开发时随手记录的,先简单介绍一下注解、然后写一个小Demo加深印象。

Annotation官网描述

The common interface extended by all annotation types. Note that an interface that manually extends this one does not define an annotation type. Also note that this interface does not itself define an annotation type.

大致的意思是:所有的注解类型接口都继承Annotation接口,自定义继承Annotation不会定义注解类型。

个人认为:注解就相当于代码注释一样,然后我们可以通过获取到其属性做一下相关操作,从而优化整个项目。

基本介绍:

​ 举例介绍

1
2
3
4
5
6
7
//本身BindView是一个注解,@Retention
@Retention(RetentionPolicy.CLASS)
@Target(ElementType.FIELD)
public @interface BindView {
//可以给定一个默认值
@IdRes int value() default -1;
}

继承至Annotation接口的接口,如@BindVeiw、@Retention、@Target都属于注解,但是@Retention、@Target又有区别,它们定义为:元注解

元注解定义:

​ 定义在注解上面的注解,我们就称为元注解,它与一般注解的区别就在于Target的作用范围,举例说明

1
2
3
4
5
6
7
8
//@Documented 将注解中的元素包含到 Javadoc 中去
@Documented
@Retention(RetentionPolicy.RUNTIME)
//这里作用于ANNOTATION_TYPE,所以@Retention属于元注解
@Target({ElementType.ANNOTATION_TYPE})
public @interface Retention {
RetentionPolicy value();
}
下面主要介绍@Retention、@Target、@Documented、@Inherited四种常见注解
注解 描述
@Retention 用来定义注解的生命周期,由RetentionPolicy枚举类定义
SOURCE:注解在编译器时就会丢弃,不会保留在编译后的class文件中
CLASS:注解会保留在class文件中,但是不会加载到JVM中,在运行时候反射是无法获取到相关注解属性
RUNTIME:从编译、加载、运行期间会一直保留,可以通过反射的方式获取
@Target 注解的作用域,ElementType枚举类定义
CONSTRUCTOR:注解用于 构造函数
FIELD:注解用于 成员变量(包括枚举)
LOCAL_VARIABLE:注解用于 局部变量
METHOD:注解用于 方法
PACKAGE:注解用于 包
PARAMETER:注解用于 方法中参数
TYPE:注解用于 类、接口、枚举类
ANNOTATION_TYPE:注解用于 注解,该注解属于元注解
@Documented 表示注解会被包含在Java API文档中
@Inherited 允许子类继承父类的注解
自定义注解

自定义@BindView注解

1
2
3
4
5
6
@Retention(RetentionPolicy.CLASS)
@Target({ElementType.FIELD})
public @interface BindView {

@IdRes int value() default -1;
}
解析注解
  • 通过反射的方式,在运行时期获取 value
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
public class MainActivity extends AppCompatActivity {

@BindView(R.id.tv_content)
public TextView mTvContent;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

Class<? extends MainActivity> clazz = getClass();
try {
Field mTvContent = clazz.getField("mTvContent");
//属性字段上是否为@BindView修饰
if (mTvContent.isAnnotationPresent(BindView.class)) {
BindView annotation = mTvContent.getAnnotation(BindView.class);
//是否是@BindView注解
if (null == annotation) {
Log.e("TAG", "未获取到相关注解: ");
} else {
Log.e("TAG", "annotation value is " + annotation.value() + " mTvContent id is " + R.id.tv_content);
}
} else {
Annotation[] annotations = mTvContent.getAnnotations();
Log.e("TAG", "注解长度: "+annotations.length);
if (0==annotations.length) {
Log.e("TAG", "未获取到相关注解");
}
}
} catch (NoSuchFieldException e) {
e.printStackTrace();
}
}
}

打印的结果:

TAG: 注解长度: 0
未获取到相关注解

打印结果没有问题,因为@BindView的生命周期为 CLASS ,注解虽然会保留在class文件中,但是不会加载到JVM中, 所以我们在运行时候反射是无法获取到相关注解属性。

  • 修改BindView之后
1
2
3
4
5
6
7
//修改为 RUNTIME 
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD})
public @interface BindView {

@IdRes int value() default -1;
}

打印的结果:
TAG: annotation value is 2131165325 mTvContent id is 2131165325

修改了注解的Retention之后,可以正常获取value值,所以注解在使用时多多注意@Target、@Retention使用。

下节介绍

注解相关的描述到此就结束了,下一节先介绍如何配置AS,让我们能够debug编译时期代码,然后再介绍通过APT编写自定义ButterKnife。感谢观看。

# 注解
EventBus巧用APT插件提升性能
如何调试AbstractProcessor
  • 文章目录
  • 站点概览
欢亮

欢亮

天下事有难易乎?为之,则难者亦易矣;不为,则易者亦难矣。
9 日志
6 分类
10 标签
GitHub E-Mail
Links
  • 二松同学
  1. 1. 为什么会有本篇文章?
  2. 2. Annotation官网描述
  3. 3. 基本介绍:
  4. 4. 元注解定义:
  5. 5. 下面主要介绍@Retention、@Target、@Documented、@Inherited四种常见注解
  6. 6. 自定义注解
  7. 7. 解析注解
  8. 8. 下节介绍
© 2019 欢亮 | 121k | 1:50
由 Hexo 强力驱动 v3.9.0
|
主题 – NexT.Muse v7.3.0