什么是注解
用@…标记,实现额外的功能。类似python中的装饰器。就是一种装饰模式。
分类:
- SOURCE类型的注解主要由编译器使用
- CLASS类型的注解主要由底层工具库使用,涉及到class的加载
- RUNTIME类型的注解经常使用,还需要能手动编写。注意千万不要漏写
@Retention(RetentionPolicy.RUNTIME)
,否则运行期无法读取到该注解。
使用注解的方式:
package oop_package.src.com.itranswarp.sample;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class Main {
public static void main(String[] args) throws ReflectiveOperationException {
Person p = new Person();
p.name = "abc";
p.city = "shanghai";
check(p); //使用检查函数
System.out.println(p.city);
}
//自定义注解逻辑功能
static void check(Person person) throws IllegalArgumentException, ReflectiveOperationException {
// 遍历所有Field:
for (Field field : person.getClass().getFields()) {
// 获取Field定义的@Range:
Range range = field.getAnnotation(Range.class);
// 如果@Range存在:
if (range != null) {
// 获取Field的值:
Object value = field.get(person);
// 如果值是String:
if (value instanceof String) {
String s = (String) value;
// 判断值是否满足@Range的min/max:
if (s.length() < range.min() || s.length() > range.max()) {
throw new IllegalArgumentException("Invalid field: " + field.getName());
}
}
}
}
}
}
//定义注解
@Retention(RetentionPolicy.RUNTIME) //运行期间可以使用
@Target(ElementType.FIELD)
@interface Range {
int min() default 0;
int max() default 255;
}
//使用注解
class Person {
@Range(min=5, max=20)
public String name;
@Range(max=10)
public String city;
}
通过@Range注解,配合check()方法,就可以完成Person实例的检查。
检查逻辑完全是自定义的,JVM不会自动给注解添加任何额外的逻辑。
例如,JUnit是一个测试框架,它会自动运行所有标记为@Test的方法。
定义注解 @interface
基本步骤:
- 用
@interface
定义; - 添加参数、默认值,最常见的参数定义为
value()
; - 用元注解配置注解;
public @interface Report {
int type() default 0; //default设定默认值
String level() default "info";
String value() default "";
}
元注解 meta annotation
能注解其它注解。
@Target 定义注解能用在哪些位置
例如可用于方法:
@Target(ElementType.METHOD)
public @interface Report {
...
}
可用于方法和字段:
@Target({
ElementType.METHOD,
ElementType.FIELD
})
public @interface Report {
...
}
@Retention 定义注解生命周期
仅编译期: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 注解可重复
@Repeatable
public @interface Report {
...
}
@Report(type=1, level="debug")
@Report(type=2, level="warning")
public class Hello {
}
@Inherited 子类是否可继承父类注解
@Inherited
@Target(ElementType.TYPE)
public @interface Report {
int type() default 0;
String level() default "info";
String value() default "";
}
@Report(type=1)
public class Person {
}
public class Student extends Person { //子类也具有@Report注解
}
reflect 注解
可以通过reflect查看一个类是否被注解过,获取注解等操作:
// 判断@Report是否存在于Person类:
Person.class.isAnnotationPresent(Report.class);
// 获取Person定义的@Report注解,若不存在则返回null
Report report = Person.class.getAnnotation(Report.class);