看看 Java 的注解

Feb 08 2020

写 Java 的时候时不时能接触到注解的代码。就是那个在类或者方法上出现 @ 符号的地方,比如在方法中使用泛型的时候,如果没有检查类型,IDEA 会自动警告提示,此时在方法名上添加 @SuppressWarnings(“unchecked”) 就可以消除这个警告

那么今天就先从这个 SuppressWarnings 入手开始简单分析下注解是什么

1
2
3
4
5
@Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE})
@Retention(RetentionPolicy.SOURCE)
public @interface SuppressWarnings {
String[] value();
}

我们看到 SuppressWarnings 是一个 @interface 的 Java 类型,表示它是一个 Annataion (注解)

看到它被 @Retention 和 @Target 进行了修饰,用来修饰注解的叫做元注解,在 Java 中有这样几个元注解:

@Retention、 @Target、 @Document、 @Inherited和@Repeatable(Java 8 加入)

@Retention

表示被修饰的注解生效范围,像 SuppressWarnings 中是 SOURCE,表示 SuppressWarnings 只是作用在源代码,不会生成到 class 文件中。其他的几个作用范围是:

默认值,表示注解会在 class 文件中存在,但运行时无法获取到

表示注解会在 class 文件中存在,在运行时可以通过反射获取到

因此,如果是我们自定义注解,那么肯定要使用 RUNTIME 的方式才有意义

@Target

表示被修饰的注解作用的范围

所以 SuppressWarnings 是可以用于类,接口,方法,成员变量,方法参数,构造方法,局部变量的注解

以上两个注解是使用得比较多的,其他的几个元注解今天暂不介绍。注解在 Java 代码中主要是用来读取数据用的,既然我们定义好了自己的注解,那么读取的话,使用的是反射

读取注解

判断是否存在对应的 Annatation 对象

获取对应的 Annatation 对象

获取所有对应的 Annatation 对象组

给一个自定义注解例子,并获取值

在这个例子中,自定义注解 MyAnnotation,作用于类,域字段以及方法

对 Test 类以及它的字段和方法都使用该注解修饰,并通过反射获取它们的值

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
40
41
42
43
44
45
46
@Target({ElementType.TYPE, ElementType.FIELD, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@interface MyAnnotation {
String[] value();
}


@MyAnnotation("className")
public class Test {
@MyAnnotation("fieldName")
String field;

@MyAnnotation("methodName")
public void method(){

}

public static void main(String[] args) {
Class<Test> klass = Test.class;

// 判断是否存在类注解
boolean hasClassAnno = klass.isAnnotationPresent(MyAnnotation.class);
if (hasClassAnno){
// 获取该注解
MyAnnotation myAnnotation = klass.getAnnotation(MyAnnotation.class);
// 提取注解的值
System.out.println(Arrays.toString(myAnnotation.value()));
}

try {
Field field = klass.getDeclaredField("field");
if (field.isAnnotationPresent(MyAnnotation.class)){
MyAnnotation myAnnotation = field.getAnnotation(MyAnnotation.class);
System.out.println(Arrays.toString(myAnnotation.value()));
}

Method method = klass.getMethod("method");
if (method.isAnnotationPresent(MyAnnotation.class)){
MyAnnotation myAnnotation = method.getAnnotation(MyAnnotation.class);
System.out.println(Arrays.toString(myAnnotation.value()));
}
} catch (NoSuchFieldException | NoSuchMethodException e) {
e.printStackTrace();
}
}
}

今天的介绍就到这里,现在是疫情攻坚期,祈祷武汉尽快挺过难关,中国尽快挺过难关