分类
- 由编译器使用的注解:此类注解不会进入.class文件,被编译后就被扔掉了(SOURCE)
- @Override:让编译器检查该方法是否正确地实现了覆写;
- @SuppressWarnings:告诉编译器忽略此处代码产生的警告。 - 由工具处理.class文件使用的注解:这类注解一般不会自己处理,而是一些工具自动加载(CLASS)
- 最常用的注解:在程序运行期间能够读取的注解,加载后存在在JVM中。(RUNTIME)
根据以上分类,因此我们经常使用的将是RUNTIME类型的注,并且学习的也是。
大部分注解会有一些配置参数:最常用的是value,如果配置参数不填,则为默认值。
如果参数名称是value,且只有一个参数,那么可以省略参数名称。
定义注解:
在java中我们可以自己定义注解,格式如下:
- 第一步,用@interface定义注解
- 第二步,添加参数、默认值(最常用的参数定义为value)
- 第三步,用元注解配置注解
定义注解@Report
public @interface Report {
int type() default 0;//注解的参数,类似于无参方法,default设置默认值
String level() default "info";
String value() default "";
}
元注解:可以修饰其他注解的注解叫做元注解
java中已经定义了一些元注解,通常我们只需要使用而不需要去编写。
-
@Target:在定义注解时添加,它可以将注解定义在用于源码的那些位置:
- 类或接口:ElementType.TYPE;
- 字段:ElementType.FIELD;
- 方法:ElementType.METHOD;
- 构造方法:ElementType.CONSTRUCTOR;
- 方法参数:ElementType.PARAMETER。@Target(ElementType.METHOD)//定义注解@Report可用在方法中 public @interface Report { int type() default 0; String level() default "info"; String value() default ""; }
-
@Retention:定义了注解的生命周期,若不定义则默认class阶段
- 仅编译期:RetentionPolicy.SOURCE;
- 仅class文件:RetentionPolicy.CLASS;
- 运行期:RetentionPolicy.RUNTIME。@Retention(RetentionPolicy.RUNTIME) public @interface Report { int type() default 0; String level() default "info"; String value() default ""; }
-
@Repeatable:可以定义注解(Annotation)是否可重复
最终注解可以如下:@Report(type=1, level="debug") @Report(type=2, level="warning") public class Hello { }
-
@Inherited:定义子类是否可以继承父类定义的注解。(只针对@Target为类或接口类型有效)
使用反射读取注解:
所有的注解都继承自java.lang.annotation.Annotation,因此,读取注解,需要使用反射API。
方法包括:
判断注解是否存在类、字段、方法或是构造方法中:
- Class.isAnnotationPresent(Class) (类)
- Field.isAnnotationPresent(Class) (字段)
- Method.isAnnotationPresent(Class) (方法)
- Constructor.isAnnotationPresent(Class) (构造方法)
例如,判断@Report是否存在Person类中
Person.class.isAnnotationPresent(Report.class);
利用反射读取注解值:
- Class.getAnnotation(Class)
- Field.getAnnotation(Class)
- Method.getAnnotation(Class)
- Constructor.getAnnotation(Class)
例:
// 获取Person定义的@Report注解:
if (cls.isAnnotationPresent(Report.class)) {
Report report = Person.class.getAnnotation(Report.class);
}
int type = report.type();
String level = report.level();
利用反射读取注解可能会有空值返回因此,在获取值之前要先判断。
注解使用
注解如何使用,由程序自己决定。
该注解定义一个字段的规则
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface Range {
int min() default 0;
int max() default 255;
}
public class Person {
@Range(min=1, max=20)
public String name;
@Range(max=10)
public String city;
}