Java注解
一种特殊注释–注解
- 注释会被编译器忽略,而注解被编译器打包进class,因此注解是一种用作标注的元数据。
分为三类:
- 不会被编译进
.class
@override
:告诉编译器检查该方法是否正确实现了覆写@SuppressWarnings
:告诉编译器忽略此处警告
- 不会被编译进
- 由工具处理
.class
文件使用的注解,比如有些工具会在加载class的时候,对class做动态修改,实现一些特殊功能
- 这类注解会被编译进入
.class
文件,加载结束后不会存在于内存 - 这类注解只被一些底层库使用,一般我们不必自己处理
- 由工具处理
- 程序中能够读取的注解,加载后一直存在于JVM,定义配置参数可以包括:
- 所有基本类型
- String
- 枚举类型
- 基本类型,String以及枚举的数组
定义注解:
- 使用`@interface`语法定义注解(Annotation),它的格式如下:
1
2
3
4
5
6
public Report {
int type() default 0; //default设定一个默认值
String level() default "info";
String Value() default "";
}
元注解(用来修饰其他注解的注解)
最常用的元注解是
@Target
使用
@Target
可以定义Annotation
能够被应用于源码的哪些位置:- 类或接口:
ElementType.TYPE
; - 字段:
ElementType.FILED
; - 方法:
ElementType.METHOD
; - 构造方法:
ElementType.CONSTRUCTOR
; - 方法参数:
ElementType.PARAMETER
;
- 类或接口:
如电话已注解
@Report
可用在方法上,我们必须添加一个@Target(ElementType.METHOD)
:1
2
3
4
5
6
public Report{
int type() default 0;
String level default "info";
String value() default "";
}定义多个注解,可以用数组
1
2
3
@Retention(定义注解的生命周期)
- 仅编译器:
RetentionPolicy.SOURCE
; - 仅class文件:
RetentionPolicy.CLASS
; //默认为CLASS - 运行期:
RetentionPolicy.RUNTIME
;
- 仅编译器:
@Repeatable(定义注解是否可重复)
1 |
|
- Inherited(定义子类是否可以继承父类定义的注解)
- 仅对@Target(ElementType.TYPE)类型有作用
- 仅针对class的继承,对interface继承无效
处理注解
SOURCE类注解有编辑器使用,一般我们只使用,不编写。CLASS类型注解主要由底层工具库使用,涉及class加载,我们很少用到。只有RUNTIME
类的注解不但使用还需要经常编写。
注解定义后也是一种class,继承自java.lang.annotation.Annotation
,读取注解需要使用反射API。
JAVA提供反射API读取注解的方法:
- 判断某个注解是否存在于class、Filed、Method、Constructor
- Class.isAnnotationPresent(Class)
- Filed.isAnnotationPresent(Class)
- Method.isAnnotationPresent(Class)
- Constructor.isAnnotationPresent(Class)
1
Person.class.isAnnotationPresent(Report.class); //判断@report是否存在 于Person类内
- 读取注解
- Class.getAnnotation(Class)
- Filed.getAnnotation(Class)
- Method.getAnnotation(Class)
- Constructor.getAnnotation(Class)
1 | Reprot report = Person.class.getAnnotation(Report.class); |
使用注解
注解如何使用,完全由程序自己决定。例如,JUnit是一个测试框架,会自动运行所有标记为@Test的方法。
1 | //定义注解 |