Java基础-注解
参考文献
注解概念
- Java注解(Annotation)又称 Java 标注,是 JDK5.0 引入的一种注释机制.重点:和
javadoc
不同,Java 标注可以通过反射获取标注内容. - 在编译器生成类文件时,标注可以被嵌入到字节码中.Java 虚拟机可以保留标注内容,在运行时可以获取到标注内容
- 注解是JDK1.5版本开始引入的一个特性,用于对代码进行说明,可以对包、类、接口、字段、方法参数、局部变量等进行注解.它主要的作用有以下四方面:
- 生成文档,通过代码里标识的元数据生成
javadoc
文档. - 编译检查,通过代码里标识的元数据让编译器在编译期间进行检查验证.
- 编译时动态处理,编译时通过代码里标识的元数据动态处理,例如动态生成代码.
- 运行时动态处理,运行时通过代码里标识的元数据动态处理,例如使用反射注入实例
- 生成文档,通过代码里标识的元数据生成
- 注解是对代码的一种增强,可以在代码编译或者程序运行期间获取注解的信息,然后根据这些信息做各种事情。
Java自带的标准注解
@Override
重写
- 概念:检查该方法是否是重写方法.如果发现其父类,或者是引用的接口中并没有该方法时,会报编译错误.
@Deprecated
过期警告
- 概念:标记过时方法.如果使用该方法,会报编译警告.在开发中,我们经常能遇到这样的情况
@SuppressWarnings
忽略警告
- 概念:指示编译器去忽略注解中声明的警告.
元注解
@Retention
指定注解的保留策略
-
概念:表示在什么级别保存该注解信息.在实际开发中,一般都写
RUNTIME
,除非项目有特殊需求注解是代码的特殊标记,可以在编译(
RetentionPolicy.SOURCE
),类加载(RetentionPolicy.CLASS
),运行时被读取(RetentionPolicy.RUNTIME
) -
SOURCE
和CLASS
分别需要基础AbstractProcessor
,实现process
方法去处理自定义注解 -
RUNTIME
是日常开发中用的最多的,配合Java反射机制
1 | public enum RetentionPolicy { |
@Documented
作用文档
- 概念:将此注解包含在
javadoc
中 ,它代表着此注解会被javadoc
工具提取成文档. - 无参的注解,作用域为
RetentionPolicy.RUNTIME
,运行时有用!这个只是用来作为标记,了解即可,在实际运行后会将该注解写入javadoc
中,方便查看.
@Target
目标
-
概念:标记这个注解应该是使用在哪种 Java 成员上面
-
注意这里是数组格式的参数,证明可以传多个值.
@Target(ElementType.TYPE)
——接口、类、枚举、注解@Target(ElementType.FIELD)
——字段、枚举的常量@Target(ElementType.METHOD)
——方法@Target(ElementType.PARAMETER)
——方法参数@Target(ElementType.CONSTRUCTOR)
——构造函数@Target(ElementType.LOCAL_VARIABLE)
——局部变量@Target(ElementType.ANNOTATION_TYPE)
——注解@Target(ElementType.PACKAGE)
——包
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
46public enum ElementType {
/** Class, interface (including annotation type), or enum declaration */
TYPE,
/** Field declaration (includes enum constants) */
FIELD,
/** Method declaration */
METHOD,
/** Formal parameter declaration */
PARAMETER,
/** Constructor declaration */
CONSTRUCTOR,
/** Local variable declaration */
LOCAL_VARIABLE,
/** Annotation type declaration */
ANNOTATION_TYPE,
/** Package declaration */
PACKAGE,
/**
* Type parameter declaration
*
* @since 1.8
*/
TYPE_PARAMETER,
/**
* Use of a type
*
* @since 1.8
*/
TYPE_USE,
/**
* Module declaration.
*
* @since 9
*/
MODULE
}
@Inherited
继承
- 概念:标记这个注解是继承于哪个注解类(默认注解并没有继承于任何子类).
- 让子类可以继承父类中被
@Inherited
修饰的注解,注意是继承父类中的,如果接口中的注解也使用@Inherited
修饰了,那么接口的实现类是无法继承这个注解的
1 | import java.lang.annotation.*; |
新注解
从 Java 7 开始,额外添加了 3 个注解:
@SafeVarargs
- Java 7 开始支持,忽略任何使用参数为泛型变量的方法或构造函数调用产生的警告.@FunctionalInterface
- Java 8 开始支持,标识一个匿名函数或函数式接口.@Repeatable
- Java 8 开始支持,标识某注解可以在同一个声明上使用多次.
自定义注解
定义注解
-
jdk中注解相关的类和接口都定义在
java.lang.annotation
包中。 -
注解的定义和我们常见的类、接口类似,只是注解使用
@interface
来定义,如下定义一个名称为MyAnnotation的注解:1
2
3public MyAnnotation {
}
注解中定义参数
-
注解有没有参数都可以,定义参数如下:
1
2
3
4
5public 注解名称{
[public] 参数类型 参数名称1() [default 参数默认值];
[public] 参数类型 参数名称2() [default 参数默认值];
[public] 参数类型 参数名称n() [default 参数默认值];
}- 注解中可以定义多个参数,参数的定义有以下特点:
- 访问修饰符必须为
public
,不写默认为public - 该元素的类型只能是基本数据类型、String、Class、枚举类型、注解类型(体现了注解的嵌套效果)以及上述类型的一位数组
- 该元素的名称一般定义为名词,如果注解中只有一个元素,请把名字起为value(后面使用会带来 便利操作)
- 参数名称后面的
()
不是定义方法参数的地方,也不能在括号中定义任何参数,仅仅只是一个特殊的语法 default
代表默认值,值必须和第2点定义的类型一致- 如果没有默认值,代表后续使用注解时必须给该类型元素赋值
- 访问修饰符必须为
- 注解中可以定义多个参数,参数的定义有以下特点:
注解信息的获取
-
为了运行时能准确获取到注解的相关信息,Java在
java.lang.reflect
反射包下新增了AnnotatedElement
接口,它主要用于表示目前正在虚拟机中运行的程序中已使用注解的元素,通过该接口提供的方法可以利用反射技术地读取注解的信息.类 说明 Package
用来表示包的信息 Class
用来表示类的信息 Constructor
用来表示构造方法信息 Field
用来表示类中属性信息 Method
用来表示方法信息 Parameter
用来表示方法参数信息 TypeVariable
用来表示类型变量信息,如: 类上定义的泛型类型变量,方法上面定义的泛型类型变量
AnnotatedElement
常用方法
返回值 | 方法名称 | 说明 |
---|---|---|
<A extends Annotation> |
getAnnotation(Class<A> annotationClass) |
该元素如果存在指定类型的注解,则返回这些注解,否则返回 null |
Annotation[] |
getAnnotations() |
返回此元素上存在的所有注解,包括从父类继承的 |
boolean |
isAnnotationPresent(Class<? extends Annotation> annotationClass) |
如果指定类型的注解存在于此元素上,则返回 true,否则返回 false |
Annotation[] |
getDeclaredAnnotations() |
返回直接存在于此元素上的所有注解,注意,不包括父类的注解,调用者可以随意修改返回 的数组;这不会对其他调用者返回的数组产生任何影响,没有则返回长度为0的数组 |
解析类上的注解
1 |
|
解析类上的类型变量
1 |
|
解析字段上的注解
1 |
|
解析泛型字段map上的注解
1 |
|
解析构造函数上的注解
1 |
|
解析方法参数注解
1 |
|
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 HoleLin's Blog!