首页 > 技术文章 > Annotation--注解

gaogzhen 2019-06-01 10:39 原文

一、synopsis

  注解,可以看作是对 一个 类/方法 的一个扩展的模版,每个 类/方法 按照注解类中的规则,来为 类/方法 注解不同的参数,在用到的地方可以得到不同的 类/方法 中注解的各种参数与值
  注解也就是Annotation,相信不少人也和我之前一样以为和注释和doc一样,是一段辅助性的文字,其实注解不是这样的。
  从JDK5开始,java增加了对元数据(描述数据属性的信息)的支持。其实说白就是代码里的特殊标志,这些标志可以在编译,类加载,运行时被读取,并执行相应的处理,以便于其他工具补充信息或者进行部署。

二、内置注解

1、@Override

  限定父类重写方法

2、@Deprecated

&emsp: 标志方法已过时

3、@SupressWarning

  抑制编译器警告

4、@SafeVarargs

  堆污染警告:把不带泛型的对象赋给一个带泛型的对象

5、@Functionallnterface

  函数式接口:如果接口中只有一个抽象方法(可以包含多个默认方法或多个static方法)

三、自定义注解

1、syntax--语法

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
...  

public @interface MyAnnotation{ property//属性; method//方法;}

2、analysis--解析

2.1、builtin annotation--元注解或内置注解

2.1.1、@Target--修饰那些程序单元

  @Target也只能修饰一个注解定义,作用是指定被修饰的注解能用于修饰哪些程序单元,@Target也包含了一个value值,他的值只能是下面的:ElementType.

取值 注解使用范围
METHOD 可用于方法上
TYPE 可用于类或者接口上
ANNOTATION_TYPE 可用于注解类型上(被@interface修饰的类型)
CONSTRUCTOR 可用于构造方法上
FIELD 可用于域上
LOCAL_VARIABLE 可用于局部变量上
PACKAGE 用于记录java文件的package信息
PARAMETER 可用于参数上

  例如:@Target(ElementType.METHOD)

2.1.2、@Rentention--被修饰的注解可以保存位置

  这个注解是用来修饰注解定义的,作用是被修饰的注解可以保存多久,这个注解需要使用参数。
  这个参数的类型是RetentionPolicy,所以使用这个注解就要对value赋值。
  value的值有且仅有三个:

  • RetenionPolicy.CLASS 编译器把该注解记录在class文件中。当运行java程序时,JVM不可获取注解信息。这是默认值!
  • RetenionPolicy.RUNTIME编译器把该注解记录在class文件中。当运行java程序时,JVM可获取注解信息,程序可以通过反射获取该注解信息
  • RetenionPolicy.SOURCE 该注解只保存在源代码中,编译器直接丢弃该注解

  例如:@Retention(RetenionPolicy.SOURCE)

2.1.3、@Documented--被修饰的注解类将被javadoc工具提取成文档

  这个注解用于指定被修饰的注解类将被javadoc工具提取成文档,如果定义注解类时使用了这个注解修饰,则所有使用该注解修饰的程序员苏API文档将会包含该注解说明。
  例如:@Documentedpublic @interface Testable{}

2.1.4、@Inherited--被修饰的注解类将被子类继承

  这个注解指定被他修饰的注解将具有继承性——如果某个类使用了@Xxx,则其子类将自动被@Xxx修饰

2.1.5、@Result --相同类型注解使用多次

  作用是在同一个程序元素前使用多个相同类型的注解在java8之前只能通过@Results配置,
  java8简化了它的写法例如:
  @test(age=5)@test(age=8)public void resultTest(){}

3、example--示例

  @Check注解类

package mannotation;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * @auth Administrator
 * @date 2019-06-01 09:36
 */
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Check {
}

  Calculator类

package mannotation;

/**
 * 简单模拟计算器类
 * @auth Administrator
 * @date 2019-06-01 09:48
 */
public class Calculator {

	/**
	 * addition
	 */
	@Check
	public void add() {
		System.out.println("1+0="+(1+0));
		String s = null;
		s.length();
	}
	/**
	 * subtraction
	 */
	@Check
	public void sub() {
		System.out.println("1-0="+(1-0));
	}
	/**
	 * multiplication
	 */
	@Check
	public void mul() {
		System.out.println("1*0="+(1*0));
	}
	/**
	 * division
	 */
	@Check
	public void div() {
		System.out.println("1/0="+(1/0));
	}
}

  CalculatorTest类

package mannotation;

import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

/**
 * 测试文件
 * @auth Administrator
 * @date 2019-06-01 10:00
 */
public class CalculatorTest {
	public static void main(String[] args) throws IOException {
		int exces = 0;//出现异常次数
		// 1、新建计算器类对象
		Calculator cl = new Calculator();
		// 2、获取计算器类的字节码对象
		Class   ca = Calculator.class;
		// 3、获取所有方法
		Method[] methods = ca.getDeclaredMethods();
		// 4、过滤带有注解类@check的方法
		// 5、将调试信息打印到日志文件cal_debug.log中
		// 5.1、获取日志文件cal_debug.log输入流
		BufferedWriter bw = new BufferedWriter(new FileWriter("cal_debug.log"));
		for (Method method: methods) {
			if (method.isAnnotationPresent(Check.class)) {
				try {
					method.invoke(cl);
				} catch (Exception e) {
					exces++;
					bw.write("method "+method.getName()+" 出现异常");
					bw.newLine();
					bw.write("exception name:"+e.getCause().getClass().getSimpleName());
					bw.newLine();
					bw.write("exception type:"+e.getCause().getMessage());
					bw.newLine();
					bw.write("------------------------------");
				}
			}
		}
		bw.newLine();
		bw.write("exception counts:"+exces);
		bw.close();
	}
}

  测试结果:cal_debug.log内容

method add 出现异常
exception name:NullPointerException
exception type:null
------------------------------method div 出现异常
exception name:ArithmeticException
exception type:/ by zero
------------------------------
exception counts:2

参考文档:https://baike.baidu.com/item/%E6%B3%A8%E8%A7%A3/22344968
参考视频:
咨询邮箱:gaogzhen@foxmail.com

推荐阅读