随机名言

注解



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将具有继承性,即被修饰的类其子类也会有该注解的功能


posted @ 2020-02-02 16:07  Howlet  阅读(188)  评论(0编辑  收藏  举报

Copyright © By Howl