Java注解Annotation

概述

注解(Annotation):是元数据的一种形式,能够添加到Java源代码,Java中的类、方法、变量、参数、包都可以被注解。注解对他们所注解的代码没有直接的影响。

注解的使用可以简化代码,提高开发效率。

在Android中,用到注解的开源库有:Retrofit、ButterKnife、Dagger。

Annotation分类

标准Annotation

标准Annotation是指Java自带的几个Annotation:

@Override@Deprecated@SuppressWarnings

元Annotation

元Annotation是指用来定义Annotation的Annotation:

@Documented:保存到Javadoc文档中。

@Retention:保留时间,可选值SOURCE(源码)、CLASS(编译时)、RUNTIME(运行时);默认为CLASSSOURCE大都为Mark Annotation,这类Annotation大都用来校验,如Override。

@Target:表示该注解可以修饰那些程序元素,值为:TYPEMETHODCONSTRUCTORFIELDPARAMETER等,未标记则表示可修饰所有。

@Inherited:是否可以被继承,默认为false。

自定义Annotation

根据自己需要进行自定义的Annotation,定义时需要用到上面的元Annotation。

Annotation自定义

定义

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@Inherited
public @interface Request {

String GET = "get";
String POST = "post";

String host();

String path();

int version() default 1;

String method();
}

语法说明

  1. 通过@interface定义,注解类名即为注解名;

  2. 注解配置参数为注解类的方法名:

    (1)所有的方法没有方法体,没有参数,没有修饰符,不允许抛出异常;

    (2)方法的返回值只能是基本类型、String、Class、enum、Annotation、及他们的一维数组;

    (3)若只有一个默认属性,可直接用value()函数;

    (4)若一个属性都没有的表示该Annotation为标记注解(Mark Annotation)如@Override;

    (5)可以加default表示默认值。

调用

1
2
3
4
5
6
7
8
9
10
11
12
public class HttpUtil {

@Request(host = "https://api.github.com/", path = "users", method = Request.GET)
public void request1() {

}

@Request(host = "https://api.github.com/", path = "users/xch168/repos", method = Request.POST, version = 2)
public void request2() {

}
}

Annotation解析

运行时Annotation解析

(1)运行时Annotation指@RetentionRUNTIME的Annotation。

(2)常用API

1
2
3
4
5
6
// 获取该Target的某个Annotation的信息
method.getAnnotation(AnnotationName.class);
// 获取该Target的所有Annotation
method.getAnnotations();
// 判断该Target是否被某个Annotation修饰
method.isAnnotationPresent(AnnotationName.class);

(3)解析示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public static void main(String[] args) {
try {
Class clz = Class.forName("com.github.xch168.annotationdemo.HttpUtil");
for (Method method : clz.getMethods()) {
if (method.isAnnotationPresent(Request.class)) {
Request request = method.getAnnotation(Request.class);

System.out.println("method name:" + method.getName());
System.out.println("request host:" + request.host());
System.out.println("request path:" + request.path());
System.out.println("request method:" + request.method());
System.out.println("request version:" + request.version());
System.out.println("-----------------");
}
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}

运行结果:

1
2
3
4
5
6
7
8
9
10
11
12
method name:request1
request host:https://api.github.com/
request path:users
request method:get
request version:1
-----------------
method name:request2
request host:https://api.github.com/
request path:users/xch168/repos
request method:post
request version:2
-----------------

编译时Annotation解析

(1)编译时Annotation指@RetentionCLASS的Annotation,由编译器自动解析。

(2)自定义类继承自AbstractProcessor,并重写其中的process函数。

示例代码:将上面的Request的@Retention改为CLASS:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// 表示这个Processor要处理的Annotation
@SupportedAnnotationTypes({"com.github.xch168.annotationdemo.Request"})
public class RequestProcessor extends AbstractProcessor {

/**
*
* @param annotations 表示带处理的Annotations
* @param env 表示当前或者之前的运行环境
* @return 表示这组annotations是否被这个Processor接受,如果接受,后续子Processor不会再对这个annotations进行处理
*/
@Override
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment env) {
HashMap<String, String> map = new HashMap<>();
for (TypeElement te : annotations) {
for (Element element : env.getElementsAnnotatedWith(te)) {
Request request = element.getAnnotation(Request.class);
map.put(element.getEnclosingElement().toString(), request.path());
}
}
return false;
}
}

参考链接

  1. 公共技术点之 Java 注解 Annotation
  2. 深入理解Java注解类型(@Annotation)
  3. 自定义Java注解处理器
  4. 秒懂,Java 注解 (Annotation)你可以这样学
  5. Android 中注解的使用
  6. Java 基础(十七)注解
文章目录
  1. 1. 概述
  2. 2. Annotation分类
    1. 2.1. 标准Annotation
    2. 2.2. 元Annotation
    3. 2.3. 自定义Annotation
  3. 3. Annotation自定义
    1. 3.1. 定义
    2. 3.2. 调用
  4. 4. Annotation解析
    1. 4.1. 运行时Annotation解析
    2. 4.2. 编译时Annotation解析
  5. 5. 参考链接
,