Java注解

概述

记得之前有个iOS问过我 @BindView 是什么,我说是注解,他问我什么是注解,我回答说相当于一种接口。他后面好像还问一些关于注解的问题,我一时语塞,竟然发现我天天使用的注解,要解释它的时候竟然有种说不上来的感觉。
今天想把关于注解的知识归纳一下:

  • 什么是注解
  • 有啥用
  • 应用场景
  • 如何自定义

简介

定义

注解是Java的一种类型,相当于class,interface一样,基本作用是作用和解释Java代码

优点

简化使用,降低代码量

注解分类

Java内置注解

  • 定义
    JDK已有的注解,包括以下几类:
    @Deprecated:过时注解,标记已过时的方法和类等
    @Override:复写
    @SuppressWarnings:阻止警告注解,可忽略警告
    @SafeVarargs:参数安全型注解
    @Functionallnterface:函数式接口注解

元注解

  • 定义
    相当与一种Tag标识,是Android的内置注解
  • 作用
    作用于注解,解释注解
  • 类型
    可分以下几种类型:

@Retention:保留注解,说明注解的生命周期,例如:

1
2
3
4
//用Retention来解释,RetentionPolicy.RUNTIME说明注解有生命周期
@Retention(RetentionPolicy.RUNTIME)
public @interface TestAnnotation{//定义TestAnnotation注解
}

@Documented:文档注解,将注解中的元素包含到Javadoc文档中,使用与上面类似

1
2
3
@Documented
public @interface TestAnnotation{//定义TestAnnotation注解
}

@Target:目标注解,限定了注解作用的目标范围,包括类方法等。
@Inherited:集成注解,使一个被@Inherited注解的注解作用的类的子类可以继承该类的注解,例如:

1
2
3
4
5
6
7
8
9
10
11
@Inherited
public @interface TestAnnotation{
}
... ...
@TestAnnotation
class A{
}
... ...
class B extends A{
}
//B集成了A那么且B没有被其他注解标记,那么B也被@TestAnnotation标记了

@Repearable:可重复注解,让作用的注解可以取多个值

自定义注解

我们知道注解是一种特殊的接口,所以定义起来跟普通接口相似,

1
2
3
4
5
6
7
public @interface TestAnnotation{
//注解只有成员变量,即两个属性,没有方法
//所以该注解的两个属性是no和name。方法名等于属性名
int no;
String name() default "Hello Annotation";
//default的意思是属性name默认返回的是Hello Annotation
}

定义完成后开始使用

1
2
3
4
5
@Retention(RetentionPolicy.RUNTIME)
public @interface TestAnnotation {
int id();
String getViewNo() default "HelloWord";
}

用单元测试来试下

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
35
36
37
38
39
public class TestAnnotationActivityTest {
@TestAnnotation(id = 100,getViewNo = "HelloAnnotation")
private int code1;

@TestAnnotation(id = 200,getViewNo = "HelloAnnotation")
private int code2;
@Test
public void onCreate() {
iniData();
}

private void iniData(){
setAPT();
Log.e("TestAnnotation","code1 = "+code1);
Log.e("TestAnnotation","code2 = "+code2);
}

private void setAPT() {
//获得成员变量
Field[] fields = this.getClass().getDeclaredFields();
for (Field field : fields) {
try {
//判断注解
if (field.getAnnotations() != null) {
//确定注解类型
if (field.isAnnotationPresent(TestAnnotation.class)) {
//允许修改反射属性
field.setAccessible(true);
TestAnnotation getView = field.getAnnotation(TestAnnotation.class);
Log.e("TestAnnotation",getView.getViewNo());
Log.e("TestAnnotation",getView.id()+"");
field.set(this,getView.id());//将id赋值给注解成员
}
}
} catch (Exception e) {
}
}
}
}

即使没有对code12进行初始化,也能将注解的属性复制给变量
结果

总结

注解应用的十分频繁,开发使用的第三方框架都有注解的部分,能更好的解释代码,减少代码量,降低耦合等。都是使用注解的优点。