背景
注解(Annontation)是 Java5 中引入的新特征。其用途有:
- 生成文档:如
@param
,@return
- 配置管理:如 spring 中的注解配置
- 格式检查:编译时进行格式检查,如
@override
第一个例子
VehicleInfo
VehicleInfo.java
Car
Car.java
Train
Train.java
VehicleUtil
VehicleUtil.java
MainVehicle
MainVehicle.java
原理
注解定义时使用了 @interface
,这是一个继承了 java.lang.annotation.Annotation
接口的特殊接口。
VehicleUtil.getTrafficInfo
中的 info.id()
是怎么调用的呢?
如果是通常的类实例调用过程,info
是类实例,id()
是类方法。
在本示例中,info
是 $Proxy1
类的实例,这个 proxy 类是 Java 运行时动态生成的代理类。
代理类的类方法调用都会实现了 java.lang.reflect.InvocationHandler
接口,具体到注解代理类中,类方法的调用实际执行了 sun.reflect.annotation.AnnotationInvocationHandler
类。
id()
类方法的执行过程为:
- 调用了
AnnotationInvocationHandler.invoke(Object, Method, Object[])
方法
- 在
memberValues
中,本例的值为 {type=汽车, id=1}
,找到 id
对应的值 1
- 返回
1
所以本质上,注解是一个继承了 Annotation 的特殊接口的内置的特殊接口。
元注解
在自定义注解时,需要用到一些内置的注解。这些内置的注解即为元注解,用来即注解其它的注解。
元注释有 4 个:
Documented
如果有 @Documented
注解,即做为了 public contract
的一部分,可以被工具调用,如 javadoc。
反之,如果没有 @Documented
注解,即不做为 public contract
的一部分,不可以被工具调用。
Retention
注解作用的阶段,其类型为 RetentionPolicy
,值为
- SOURCE: 会被编译器抛弃
- CLASS: 会编译在 class 文件中,但是不需要 VM 运行时加载。这个为默认值。
- RUNTIME: 会编译在 class 文件中,同时需要在 VM 运行时加载。
Target
注解作用的范围,即在哪个位置用这个注解是合法的。常见的值为:
- TYPE: 类,接口,枚举类型
- FIELD: 变量
- METHOD: 类
- PARAMETER: 形式参数
- CONSTRUCTOR: 构造方法
LOCAL_VARIABLE
: 局部变量
ANNOTATION_TYPE
: 注解
- PACKAGE: 包
TYPE_PARAMETER
: @Since 1.8, 类型参数
TYPE_USE
: @Since 1.8, 类型使用
- MODULE: @Since 9, 模块
Inherited
类型是被继承的。本文不展开解释。
Native
@Since 1.8
常量字段中的值可以被 native 代码使用。本文不展开解释。
Repeatable
@Since 1.8
注解类型是可以重复的。本文不展开解释。
常见的标准注解
- Override
- Deprecated
- SuppressWarnings
- SafeVarargs: Since 1.7
- FunctionalInterface: Since 1.8
参考
欢迎来到这里!
我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。
注册 关于