注解
1. 注解
什么是注解(Annotation)?注解是放在Java源码的类、方法、字段、参数上的一种特殊“注释”,可以在编译、类加载、运行时被读取,并执行相对应的处理
2. 基本注解
- @Override:检查该方法实现父类方法
- @Deprecated:过时注解
- @SuppressWarnings:抑制编译器警告注解
- @FunctionalInterface:函数式接口注解
3. 自定义注解
3.1 自定义定义注解
标记注解,没有任何成员变量的注解,eg:@override
public @interface MyAnnotation{
}
元数据注解,带有成员变量的注解,其中成员变量定义和方法类似,且只支持String、数组、Class、枚举、注解
public @interface MyAnnotation {
int num() default 10;
}
3.2 使用自定义注解
1. 给参数赋值
public class FooClass {
@MyAnnotation(num = 10)
public void foo(int num){
System.out.println("注解 + 反射的num为:" + num);
}
}
上面这样使用注解是没有任何作用的,那为什么我们使用@Controller就可以直接把该类改为控制器呢?因为框架为我们实现了这些功能,如果要自定义的注解也有功能,要配置反射技术来实现,下面举个栗子
接着上面的代码
public class FooClass {
@MyAnnotation(num = 10)
public void foo(int num){
System.out.println("注解 + 反射的num为:" + num);
}
public static void main(String[] args) throws InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
// 获取类
Class fooClass = FooClass.class;
// 获取类方法
for(Method method : fooClass.getMethods() ){
// 获取方法上的注解
MyAnnotation myAnnotation = method.getAnnotation(MyAnnotation.class);
if(myAnnotation != null){
// 获取注解的元数据
int num = myAnnotation.num();
// 获取对象实例
FooClass fClass = (FooClass) fooClass.newInstance();
method.invoke(fClass, num);
}
}
}
}
//输出
注解 + 反射的num为:10
注意要想使上面注解有效,必须在自定义注解上加上@Retention(RetentionPolicy.RUNTIME)
@Retention
- 这个注解是用来修饰注解的,用来指定被修饰的注解被保留多长时间
- Java文件有三个时期:编译、class、运行,注解默认在class之后失效
- 由于使用了反射,即运行期执行,要使自定义注解生效,必须加上@Retention(RetentionPolicy.RUNTIME),表示运行期该注解也生效
2. 检查实例方法
自定义注释
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Range {
int max() default 100;
}
定义一个User类
public class User {
@Range(max = 10)
public int age;
@Range()
public int age2;
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
再定义一个方法
public void check(User user) throws IllegalArgumentException, IllegalAccessException{
for(Field field : user.getClass().getFields()){
Range range = field.getAnnotation(Range.class);
if(range != null){
Object age = field.get(user);
if(age instanceof Integer){
int num = (int) age;
if(num > range.max()){
throw new IllegalArgumentException("年龄超过" + range.max());
}
}
}
}
}
测试
public static void main(String[] args) throws IllegalArgumentException, IllegalAccessException {
User user = new User();
user.setAge(11);
user.check(user);
}
输出
Exception in thread "main" java.lang.IllegalArgumentException: 年龄超过10
at annotation.User.check(User.java:29)
at annotation.User.main(User.java:43)
4. 补充
元注解用于修饰其他注解定义的
4.1 @Retention
用于指定被修饰的Annotation被保留多长时间,有SOURCE,CLASS,RUNTIME三个时期
4.1 @Target
它用于指定被修饰的Annotation用于修饰哪些程序单元,有:
TYPE 类,接口
FIELD 字段
METHOD 方法
PARAMETER 参数
CONSTRUCTOR 构造方法
LOCAL_VARIABLE 局部变量
ANNOTATION_TYPE 注解
PACKAGE
4.2 @Inherited
被修饰过的Annotation将具有继承性,即被修饰的类其子类也会有该注解的功能