一、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.
例如:@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