Java学习笔记---Annotation

下面的代码片段相信有过Android开发经验的朋友都会非常的熟悉.

1
2
3
4
5
 @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}

其中OnCreate()方法前的@Override便是今天的主角,没错它就是Java的注解Annotation.

什么是Annotation

简单的说注解就是给Java代码标上标签,让Java虚拟机知道该如何处理被标注的代码.

Java的内置Annotations

Java的注解分为:

  1. 普通注解(用于注解:类,方法,变量,参数,包)
    • @Override: 标注的方法为复写方法
    • @Deprecated: 标注的方法已过时,被弃用
    • @SuppressWarnings: 标注的方法被编译时忽略其他的注解警告
    • @SafeVarargs: 修饰”堆污染”警告
    • @FunctionalInterface: 修饰函数式接口
  2. 元注解(用于标注注解的注解)
    • @Retention: 注解保留策略
      • RetentionPolicy.SOURCE: 停留在Java源文件,被编译器丢弃
      • RetentionPolicy.CLASS: 停留在class文件中,但被虚拟机丢弃
      • RetentionPolicy.RUNTIME: 内存中的字节码,在运行时保留,可通过反射获取相关信息
    • @Target: 注解修饰目标
      • ElementType.CONSTRUCTOR: 构造器声明
      • ElementType.FIELD: 成员变量,对象,属性
      • ElementType.LOCAL_VARIABLE: 局部变量声明
      • ElementType.METHOD: 方法声明
      • ElementType.PACKAGE: 包声明
      • ElementType.PARAMETER: 参数声明
      • ElementType.TYPE: 类,接口(包括注解类型),枚举声明
    • @Documented: 注解文档提取
    • @Inherited: 注解继承声明

自定义注解

废话少说,下面我们通过注解来实现对一个person的信息注入:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
/**
* 简单的Person类
**/

public class Person {
String name;
int age;

public Person(int age, String name) {
this.age = age;
this.name = name;
}

public void display()
{

System.out.println(name+" "+age);
}
}

下面是一个自定义注解,声明了一个用于注解变量的运行时注解

1
2
3
4
5
6
@Retention(RetentionPolicy.RUNTIME) //运行时保留,可通过反射获取相关信息
@Target(ElementType.FIELD) //用于注解成员变量
public @interface PersonAnnotation {
String name() default ""; //Person的名字,默认值为空
int age(); //Person的年龄,没有默认值
}

之后我们需要对我们的注解进行处理,让它能够对我们使用了PersonAnnotation标注的Person成员变量进行自动赋值.这部分工作由下面的AnnotationPaser类完成.

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
public class AnnotationParser {

/**
* 完成对注解的处理
* @param object 持有注解目标的对象
**/

public static void parse(Object object)
{

Person p;
Class<?> clazz = object.getClass();
//获取Object对象的所有声明变量
Field[] fields = clazz.getDeclaredFields();
//遍历成员变量
for(Field f:fields)
{
//检查成员变量是否被PersonAnnotation注解修饰
if(f.isAnnotationPresent(PersonAnnotation.class)){
PersonAnnotation personAnnotation=f.getAnnotation(PersonAnnotation.class);
int age = personAnnotation.age();
String name = personAnnotation.name();
p = new Person(age,name);
//设置访问权限
f.setAccessible(true);
try {
//设置属性
f.set(object,p);
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
}
}

完成了对注解的处理后,我们的自定义注解就可以使用了.

1
2
3
4
5
6
7
8
9
10
public class Test {

@PersonAnnotation(name = "kevin",age = 20)
Person person;
public static void main(String[] args) {
Test t=new Test();
AnnotationParser.parse(t);
t.person.display();
}
}

运行结果:

1
kevin 20