Java基础:Java 注解(Annotation)及使用
Java 注解(Annotation)是 JDK 1.5 引入的特性,与类、接口、枚举是在同一等级。它可以作用在类、属性、方法、局部变量、方法参数上,用于对这些元素进行说明,注释,解释。
注解在功能上可以看成是一个接口,注解实例就是一个实现该接口的动态代理类,可在方便在程序运行期间通过反射获取该字段或方法的注解的实例,来决定下一步如何处理。
注解定义
注解 是一种标记,一种标注,一个极期相似的比喻就是标签纸,用于对其作用的目标对象进行说明,以便进行对应的操作。
有了注解,还需要对这些注解进行解析,可以通过反射机制(Reflect)访问这些注解并对其进行解析(注解解析类),没有解析的注解不起任何作用,没有任何意义的,但也不会影响代码的执行。
所有 注解 类型都继承 java.lang.annotation.Annotation
公共接口。注解的使用越来越流行,Spring Boot 框架就提供了大量的注解,由 SSM 框架的 XML 配置转为 Java 配置类,注解扮演很重要的角色,非常方便且代码更加简洁。
基本注解
定义注解与定义接口相似,只是在接口名前需要前使用 @
符号。Java 5 内置了三种基本注解:
- @Override:当前方法重写父类中的方法。
- @Deprecated:标记该目标已被弃用,不建议使用,或存在更好的替代方案。
- @SuppressWarnings:抑制编译器的警告信息。
Java 8 新增了一种注解:
- @Repeatable:支持同一个注解可重复在同一类/方法/属性上使用,更低的版是不支持的。
元注解
元注解 :作用在注解上的注解,编译器自动会对这种类注解进行解析。 JDK 提供的元注解有 @Retention
,@Target
,@Documented
,@Inherited
四个。
Spring 框架提供的很多注解,也使用了元注解。例如 Spring Boot 入口类的注解:
1 |
|
@Target
标记此类型的注解应该作用在那种 Java 成员上。该元注解只有一个属性,引用的是 java.lang.annotation.ElementType
枚举中的值。
@Target
1
2
3
4
5
6
public Target {
ElementType[] value();
}ElementType
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
36public enum ElementType {
/**
* 类,接口,枚举声明
*/
TYPE,
/**
* 字段声明(包括枚举值)
*/
FIELD,
/**
* 方法声明
*/
METHOD,
/**
* 方法参数声明
*/
PARAMETER,
/**
* 构造方法声明
*/
CONSTRUCTOR,
/**
* 局部变量声明
*/
LOCAL_VARIABLE,
/**
* 注解类型声明
*/
ANNOTATION_TYPE,
/**
* 包声明
*/
PACKAGE,
TYPE_PARAMETER,
TYPE_USE
}
@Retention
标记此类型的注解将保留多长时间(保留级别,或称为注解生命周期)。如果注解没有使用此元注解,则保留策略默认为 RetentionPolicy.CLASS
。
该元注解只有一个属性,引用的是 java.lang.annotation.RetentionPolicy
的枚举值。
@Retention
1
2
3
4
5
6
public Retention {
RetentionPolicy value();
}RetentionPolicy
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17public enum RetentionPolicy {
/**
* 只在源码中保留,将被编译器丢弃
*/
SOURCE,
/**
* 编译时会记录到CLASS文件中,但运行时忽略,默认行为。
*/
CLASS,
/**
* 编译时会记录到CLASS文件中,并在运行时由 JVM 保留,可以通过反射读取它们。
* @see java.lang.reflect.AnnotatedElement
*/
RUNTIME
}
@Document
标记将注解包含在 Javadoc 中。指示默认情况下,javadoc 和类似工具将记录带有此类型的注解,成为公共API 的一部分。
类和方法的注解,在默认情况下是不出现在 javadoc 中的。如果使用 @Document 修饰该注解,则表示此注解会出现在 javadoc 中。
1 |
|
@Inherited
标记该注解是具有继承性的,使用该元注解的注解作用的目标类的子类具体父类的注解特性。只能作用在 Annotation
类型上。
1 |
|
注解作用
注解的作用大致可分为三类:
- 生成文档:标识目标代码需要生成文档(doc)。
- 代码分析:标识对代码进行解析,使用反射实现。
- 编译检查:标识编译器可对代码进行最基本的编译检查。
注解使用
注解只有一个成员时,按规范写成 value()
,当然不这么写也不会报错。如果不设置默认值,那么使用注解时必须要传值。只有类可以被注解,接口或抽象类不能被注解。
自定义注解
自定义一个对用户年龄范围进行校验的注解,实现用户年龄范围的控制和提示。
1 |
|
注解解析
定义一个用户类 User.class
1
2
3
4
5
6public class User {
private String name;
private int age;
}对注解进行解析
1
2
3
4
5
6
7
8
9
10
11
12
13
14public static void main(String[] args) {
User user = new User().setAge(11);
Class<User> userClass = User.class;
Field[] fieldArray = userClass.getDeclaredFields();
for (Field field : fieldArray) {
AgeRange ageRange = field.getDeclaredAnnotation(AgeRange.class);
if (ageRange != null) {
if (user.getAge() > ageRange.max() || user.getAge() < ageRange.min())
System.out.println("用户年龄必须在 18 到 45 之间");
}
}
}
读取注解
1 | //读取注解信息 |
其它参考
Java基础:Java 注解(Annotation)及使用