这是我参与更文挑战的第3天,活动详情查看: 更文挑战
什么是注解
同步代码地址 github.com/xyz0z0/Andr…
注解是什么
可以说是一种辅助性的注释,可以搭配APT、字节码修改、反射技术组合出各种功能效果。
那首先认识一下注解,比如 Override,这个是系统定义的注解,主要用在子类继承父类的方法上。
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.SOURCE)
public @interface Override {
}
复制代码
可以看到第一行第二行定义了两个注解,这两个是元注解,就是用来放在注解上面的注解。第一个注解是 @Target 表示注解修饰的地方,比如这里的 ElementType.METHOD 代表该注解可以放在方法上。第二个注解 @Retention 表示注解保留到哪一个生命周期上,有三个值分别是 SOURCE(在源码中保留)、CLASS(在字节码中保留)、RUNTIME(在运行时保留),如果我们设置了保留在源码中,那么在运行时我们就无法通过反射获取到这个注释了,所以这个字段的确定需要根据实际使用场景来创建。接着就是具体的定义了 public @interface Override {} 这个按照格式来写就可以了。
注解有什么用
接着我们看看第三方开源框架 ButterKnife 中的 @BindView 注解吧。
@Retention(RUNTIME) @Target(FIELD)
public @interface BindView {
/** View ID to which the field will be bound. */
@IdRes int value();
}
复制代码
可以看到这个注解保留到运行期,可以放在成员属性上。其中还定义了一个返回值为 int 的方法,定义了方法后我们就可以在使用的时候给注解加上值了,比如这里的 @BindView(R.id.tvFirst)。
自定义一个注解
到这里注解差不多介绍完了,那我们用 Kotlin 自定义一个注解吧。顺便看看 Kotlin 里面有什么区别。
@Target(AnnotationTarget.FIELD)
@Retention(AnnotationRetention.RUNTIME)
annotation class KotlinFirst(
val name: String
)
复制代码
这里,我们就定义了一个 Kotlin 的注解,可以看到和 Java 的非常类似。我们这个注解可以放在成员属性上,保留到运行时。那么我们尝试结合反射来使用这个注解吧。
public class KotlinAnnotationTestActivity extends AppCompatActivity {
@KotlinFirst(name = "HAHA")
public String mName;
@BindView(R.id.tvFirst)
TextView tvFirst;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_chapter02);
ButterKnife.bind(this);
Class<?> clazz = this.getClass();
Field[] fields = clazz.getDeclaredFields();
for (Field field : fields) {
if (field.isAnnotationPresent(KotlinFirst.class)) {
KotlinFirst annotation = field.getAnnotation(KotlinFirst.class);
Log.d("sss", annotation.name());// HAHA
}
}
}
}
复制代码
这里我们通过反射获取到了注解上的值,接着就可以配合做一些其他操作了。
最开始我们说到注解可以配合其他技术点做一些事情,刚才我们也展示了配合反射在运行时可以读取注解的值。还可以做一些比如编译器检查,字节码修改的工作。这些就需要大家一起继续学习了。
本文是个人的学习记录,不免对技术点有错误或不够深入的理解,还望大神小白批评指教。