Loading... ![](https://blog.fivk.cn/usr/uploads/2022/03/2555972341.png) # 1、概述 * 注解:注解(Annotation),即元数据。是代码级别的说明。JDK1.5及以后版本引入了该特性,与类、接口、枚举属于同一级别。它可以声明在包、类、字段、方法、局部变量、方法参数上,以对这些元素进行说明。 * 使用方式:@注解名称 <div class="tip inlineBlock info simple"> 可以在编译时选择注解是否只存在于源码中,或者是保留在字节码(.class)文件中或者是出现在运行中。 </div> <div class="tip inlineBlock success simple"> 注释是给程序员看的 注解是给程序看的 注解是元数据 </div> # 2、作用 1. 编写文档:通过注解生成文档 2. 代码分析:通过注解对代码进行分析【反射中使用】 3. 编译检查:通过注解让编译器实现基本的编译检查【Override】 # 3、JDK中预定义的注解 * `@Override` :检测该方法是否是覆盖自父类(接口)的 * `@Deprecated` :表示该部分内容已过时 * `@SuppressWarnings` :压制警告 * 一般传递参数all `@SuppressWarnings("all")` # 4、自定义注解 ## 4.1、格式 ```java has-numbering 元注解 public @interface 注解名称{ // 属性列表(抽象方法) } ``` ## 4.2、本质 注解本质上是一个接口,该接口默认继承Annotation接口 `java.lang.annotation.Annotation` ## 4.3、属性 属性就是接口中的抽象方法。 * 要求 1. 属性的返回值类型有下列取值 * 基本数据类型 * String * 枚举 * 注解 * 以上类型的数组 2. 定义了属性,在使用时需要给属性赋值 * 如果定义属性时,使用default关键字给属性默认初始化值,则使用注解时,可以不进行属性的赋值。 * 如果只有一个属性需要赋值,并且属性的名称是value,则value可以省略,直接定义值即可。 * 数组赋值时,值使用{}包裹。如果数组中只有一个值,则{}可以省略。 ## 4.4、元注解 元注解是用于描述注解的注解。 * `@Target` :描述注解能够作用的位置 * ElementType取值: * TYPE:可以作用于类上 * METHOD:可以作用于方法上 * FIELD:可以作用于成员变量上 * `@Retention` :描述注解被保留的阶段 * `@Retention(RetentionPolicy.RUNTIME)` :当前被描述的注解,会保留到class字节码文件中,并被JVM读取到 * `@Documented` :描述注解是否被抽取到api文档中 * `@Inherited` :描述注解是否被子类继承 # 5、在程序中使用注解的属性值 1. 获取注解定义的位置的对象 (Class,Method,Field) 2. 获取指定的注解 `getAnnotation(Class)` * 自动在内存中生成了一个该注解接口的子类实现对象 3. 调用注解中的抽象方法获取配置的属性值 ```java has-numbering public class Person { public void eat() { System.out.println("eat..."); } } ``` ```java has-numbering public class Student { public void study() { System.out.println("study..."); } } ``` ```java has-numbering /** * 自定义注解 */ @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) public @interface Pro { String className(); String methodName(); } ``` ```java has-numbering @Pro(className = "com.junlong.reflect.Person", methodName = "eat") public class ReflectPro { // 不改变该类的任何代码,就可以创建任意对象,并执行其任意方法 public static void main(String[] args) throws Exception { // 1. 解析注解 // 1.1 获取该类的字节码文件对象 Class<ReflectPro> reflectClass = ReflectPro.class; // 1.2 获取指定注解 Pro annotation = reflectClass.getAnnotation(Pro.class); // 1.3 调用注解中的抽象方法,获取属性 String className = annotation.className(); String methodName = annotation.methodName(); // 2. 反射 // 2.1 加载类的字节码文件进内存 Class<?> aClass = Class.forName(className); // 2.2 创建对象 Object o = aClass.newInstance(); // 2.2 获取方法 Method method = aClass.getMethod(methodName); // 2.3 执行方法 method.invoke(o); } } ``` # 6、示例:使用注解的测试框架 ```java has-numbering @Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) public @interface Check { } ``` ```java has-numbering public class Calculator { @Check public void add() { String s = null; s.toString(); System.out.println("1 + 1 = " + (1 + 1)); } @Check public void sub() { System.out.println("2 - 1 = " + (2 - 1)); } public void mul() { System.out.println("5 * 2 = " + (5 * 2)); } @Check public void div() { int a = 3 / 0; System.out.println("3 / 2 = " + (3 / 2)); } } ``` ```java has-numbering public class TestCheck { public static void main(String[] args) throws IOException { // 1. 获取Calculator类的字节码文件对象 Calculator calculator = new Calculator(); Class<? extends Calculator> aClass = calculator.getClass(); // 2. 获取所有的方法 Method[] methods = aClass.getMethods(); // 3. 判断方法是否有@Check注解,有注解则执行 int count = 0; // 异常次数 BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter("bug.txt", true)); // 记录日志 bufferedWriter.write("======================="); bufferedWriter.newLine(); bufferedWriter.write(new Date().toString()); bufferedWriter.newLine(); bufferedWriter.write("======================="); bufferedWriter.newLine(); bufferedWriter.newLine(); for (Method method : methods) { if (method.isAnnotationPresent(Check.class)) { try { method.invoke(calculator); } catch (Exception e) { // 4. 对于异常的方法,记录日志 count++; bufferedWriter.write(method.getName() + " 方法出异常了!"); bufferedWriter.newLine(); bufferedWriter.write("名称:" + e.getCause().getClass().getSimpleName()); bufferedWriter.newLine(); bufferedWriter.write("原因:" + e.getCause().getMessage()); bufferedWriter.newLine(); bufferedWriter.write("----------------------------"); bufferedWriter.newLine(); } } } bufferedWriter.write("本次测试共出现了 " + count + " 次异常!"); bufferedWriter.newLine(); bufferedWriter.newLine(); bufferedWriter.newLine(); bufferedWriter.flush(); bufferedWriter.close(); } } ``` > 感谢小伙伴们的关注! > 你的点赞、评论、关注、收藏是对博主的最大鼓励! > 持续更新JavaSE学习笔记!欢迎订阅专栏! 最后修改:2022 年 03 月 24 日 © 允许规范转载 打赏 赞赏作者 支付宝微信 赞 1 如果觉得我的文章对你有用,请随意赞赏