JAVA-注解

注解

  1. 注解演示

    package cn.xiaoge.day22.annotation;
    
    /**
     * 注解javadoc演示
     *
     * @author xiaoge
     * @version 1.0
     * @since 1.5
     */
    
    public class AnnoDemo1 {
    
        /**
         * 计算两数只和
         * @param a 整数
         * @param b 整数
         * @return 两数的和
         */
        public int add(int a, int b){
            return a + b;
        }
    
    }
    
    
    // 运行: 在终端-->javadoc AnnoDemo1.java
    
  2. 注解_JDK内置注解

    package cn.xiaoge.day22.annotation;
    
    /**
     *  注解:
     *      概念: 说明程序的. 给计算机看的
     *      注释: 用文字描述程序的. 给程序员看的
     *
     *      定义: 注解(Annotation), 也叫元数据. 一种代码级别的说明. 他是JDK1.5及以后版本引入的一个特性,
     *      与类 接口 枚举实在同一个层次. 它可以声明在包 类 字段 方法 局部变量 方法的参数等的前面, 用来
     *      对这些元素进行说明, 注释.
     *
     *      概念描述:
     *          - JDK1.5之后的新特性
     *          - 说明程序的
     *          - 使用注解: @注解名称
     *
     *      作用分类:
     *          1. 编写文档: 通过代码里标识的注解生成文档 [生成文档doc文档]
     *          2. 代码分析: 通过代码里标识的注解对代码进行分析 [使用反射]
     *          3. 编译检查: 通过代码里标识的注解让编译器能够实现基本的编译检查 [Override]
     *
     *      JDK中预定义的一些注解
     *          - @Override: 检测被该注解标注的方法是否是继承自父类(接口)的
     *          - @Deprecated: 该注解标注的内容, 标识已过时
     *          - @SuppressWarnings: 压制警告
     *              - 一般传递参数all @SuppressWarnings("all")
     *
     *      自定义注解:
     *          格式:
     *              元注解
     *              public @interface 注解名称{}
     *
     *          本质: 注解本质上就是一个接口, 该接口默认继承Annotation接口
     *              - public interface cn.xiaoge.day22.annotation.MyAnno extends java.lang.annotation.Annotation {}
     *
     *          属性: 接口中可以定义的成员方法
     */
    @SuppressWarnings("all")
    public class AnnoDemo2 {
    
        @Override
        public String toString() {
            return super.toString();
        }
    
    
        @Deprecated
        public void show1(){
            // 有缺陷
        }
    
        // @SuppressWarnings("all") // 一般把这个注解写在类上
        public void show2(){
            // 替代show1方法
        }
    
        public void demo(){
            show1();
        }
    
    }
    
    
  3. 自定义注解

    package cn.xiaoge.day22.annotation;
    
    public @interface MyAnno {
    }
    
    
    // 运行: javac MyAnno.java  javap MyAnno.class
    
  4. 自定义注解_属性定义

    • 自定义注解
    package cn.xiaoge.day22.annotation;
    
    /**
     *
     *自定义注解:
     *    格式:
     *       元注解
     *       public @interface 注解名称{
     *           属性列表;
     *       }
     *
     *    本质: 注解本质上就是一个接口, 该接口默认继承Annotation接口
     *       - public interface cn.xiaoge.day22.annotation.MyAnno extends java.lang.annotation.Annotation {}
     *
     *    属性: 接口中可以定义的成员方法
     *      - 要求:
     *          1. 属性的返回值类型有下列取值
     *              - 基本数据类型
     *              - String
     *              - 枚举
     *              - 注解
     *              - 以上类型的数组
     *
     *          2. 定义属性, 在使用时需要给属性赋值
     *              - 如果定义属性时, 使用default关键字给属性默认初始化值, 则使用注解时, 可以不进行属性的赋值.
     *              - 如果只有一个属性需要赋值, 并且属性的名称是value, 则value可以省略, 直接定义值即可 列(@MyAnno(12))
     *              - 数组赋值时, 值使用{}包裹. 如果数组中只有一个值, 则{}省略
     *
     *      元注解: 用于描述注解的注解
     *          @Target: 描述注解能够作用的位置
     *              - ElementType取值:
     *                  - TYPE: 可以作用于类上
     *                  - METHOD: 可以作用于方法上
     *                  - FIELD: 可以作用于成员变量上
     *
     *          @Retention: 描述注解被保留的阶段
     *              - @Retention(RetentionPolicy.RUNTIME): 当前被描述的注解, 会保留到class字节码文件中, 并被JVM读取到
     *
     *          @Documented: 描述注解是否被抽取到api文档中
     *              - 加了这个注解, 用javadoc命令生成api文档是, 你那些成员方法或成员变量加了该注解, 同时也会显示到该api文档中
     *
     *          @Inherited: 描述注解是否被子类继承
     *
     *
     * 在程序使用(解析)注解: 获取注解中定义的属性值
     *      1. 获取注解定义的位置的对象     (Class, Method, Field)
     *      2. 获取指定的注解
     *          - getAnnotation(Class对象)  列(一个类Test, 获取该类的Class对象, Test.class)
     *      3. 调用注解中的抽象方法获取配置的属性值
     *
     */
    public @interface MyAnno {
    
        int value();
    
        Person per();
    
        MyAnno2 anno2();
    
        String[] strs();
    
        // String name() default "张三"; // 用该注解时, 不给name赋值, 默认就是张三
    
        /*String show2();
    
        Person pro();
        MyAnno2 mynoo();
    
        String[] show3();*/
    }
    
    
    • 注解

      package cn.xiaoge.day22.annotation;
      
      public @interface MyAnno2 {
      }
      
    • 枚举

    package cn.xiaoge.day22.annotation;
    // 枚举
    public enum Person {
        p1, p2;
    }
    
    
    
  5. 自定义注解_元注解

    • MyAnno

      package cn.xiaoge.day22.annotation;
      
      /**
       *
       *自定义注解:
       *    格式:
       *       元注解
       *       public @interface 注解名称{
       *           属性列表;
       *       }
       *
       *    本质: 注解本质上就是一个接口, 该接口默认继承Annotation接口
       *       - public interface cn.xiaoge.day22.annotation.MyAnno extends java.lang.annotation.Annotation {}
       *
       *    属性: 接口中可以定义的成员方法
       *      - 要求:
       *          1. 属性的返回值类型有下列取值
       *              - 基本数据类型
       *              - String
       *              - 枚举
       *              - 注解
       *              - 以上类型的数组
       *
       *          2. 定义属性, 在使用时需要给属性赋值
       *              - 如果定义属性时, 使用default关键字给属性默认初始化值, 则使用注解时, 可以不进行属性的赋值.
       *              - 如果只有一个属性需要赋值, 并且属性的名称是value, 则value可以省略, 直接定义值即可 列(@MyAnno(12))
       *              - 数组赋值时, 值使用{}包裹. 如果数组中只有一个值, 则{}省略
       *
       *      元注解: 用于描述注解的注解
       *          @Target: 描述注解能够作用的位置
       *              - ElementType取值:
       *                  - TYPE: 可以作用于类上
       *                  - METHOD: 可以作用于方法上
       *                  - FIELD: 可以作用于成员变量上
       *
       *          @Retention: 描述注解被保留的阶段
       *              - @Retention(RetentionPolicy.RUNTIME): 当前被描述的注解, 会保留到class字节码文件中, 并被JVM读取到
       *
       *          @Documented: 描述注解是否被抽取到api文档中
       *              - 加了这个注解, 用javadoc命令生成api文档是, 你那些成员方法或成员变量加了该注解, 同时也会显示到该api文档中
       *
       *          @Inherited: 描述注解是否被子类继承
       *
       *
       * 在程序使用(解析)注解: 获取注解中定义的属性值
       *      1. 获取注解定义的位置的对象     (Class, Method, Field)
       *      2. 获取指定的注解
       *          - getAnnotation(Class对象)  列(一个类Test, 获取该类的Class对象, Test.class)
       *      3. 调用注解中的抽象方法获取配置的属性值
       *
       */
      public @interface MyAnno {
      
          int value();
      
          Person per();
      
          MyAnno2 anno2();
      
          String[] strs();
      
          // String name() default "张三"; // 用该注解时, 不给name赋值, 默认就是张三
      
          /*String show2();
      
          Person pro();
          MyAnno2 mynoo();
      
          String[] show3();*/
      }
      
      
    • MyAnno2

      package cn.xiaoge.day22.annotation;
      
      public @interface MyAnno2 {
      }
      
    • MyAnno3

      package cn.xiaoge.day22.annotation;
      
      import java.lang.annotation.*;
      
      /**
       *  元注解: 用于描述注解的注解
       *       @Target: 描述注解能够作用的位置
       *          - ElementType取值:
       *              - TYPE: 可以作用于类上
       *              - METHOD: 可以作用于方法上
       *              - FIELD: 可以作用于成员变量上
       *
       *       @Retention: 描述注解被保留的阶段
       *          - @Retention(RetentionPolicy.RUNTIME): 当前被描述的注解, 会保留到class字节码文件中, 并被JVM读取到
       *
       *       @Documented: 描述注解是否被抽取到api文档中
       *          - 加了这个注解, 用javadoc命令生成api文档是, 你那些成员方法或成员变量加了该注解, 同时也会显示到该api文档中
       *
       *       @Inherited: 描述注解是否被子类继承
       */
      
      @Target({ElementType.TYPE, ElementType.METHOD, ElementType.FIELD})
      @Retention(RetentionPolicy.RUNTIME)
      @Documented
      @Inherited
      public @interface MyAnno3 {
      }
      
    • Worker

      package cn.xiaoge.day22.annotation;
      
      @MyAnno(value = 12, per = Person.p1, anno2 = @MyAnno2, strs = {"abc", "bbb"})
      @MyAnno3
      public class Worker {
          @MyAnno3
          public String name = "aaa";
          @MyAnno3
          public void show(){}
      
      }
      
    • Teacher

      package cn.xiaoge.day22.annotation;
      
      public class Teacher extends Worker {
      }
      
  6. 注解_解析注解

    • 注解Pro

      package cn.xiaoge.day22.annotation;
      
      import java.lang.annotation.ElementType;
      import java.lang.annotation.Retention;
      import java.lang.annotation.RetentionPolicy;
      import java.lang.annotation.Target;
      
      /**
       * 描述需要执行的类名, 和方法名
       */
      
      @Target({ElementType.TYPE})
      @Retention(RetentionPolicy.RUNTIME)
      public @interface Pro {
      
          String className();
      
          String methodName();
      
      }
      
      
      /*
          @Pro(className = "cn.xiaoge.day22.annotation.Demo1", methodName = "show")
          public class ReflectTest {
      
              public static void main(String[] args) throws Exception {
      
                  // 1.1 获取该类的字节码文件对象
                  Class<ReflectTest> reflectTestClass = ReflectTest.class;
      
                  // 其实就是在内存中生成了一个该注解接口的子类实现对象
                  Pro an = reflectTestClass.getAnnotation(Pro.class);
      
              }
      
          }
      
      
          Pro an = reflectTestClass.getAnnotation(Pro.class);
          相当于:
              public class ProImpl implements Pro{
      
                  public String className(){
                      return "cn.xiaoge.day22.annotation.Demo1";
                  }
      
                  public String classMethod(){
                      return "show";
      
                  }
      
              }
      
       */
      
    • ReflectTest

      package cn.xiaoge.day22.annotation;
      
      /*
          需求: 写一个"框架", 不能改变该类的任何代码, 可以帮我们创建任意类的独享, 并且执行其中任意方法
              实现:
                  1. 配置文件
                  2. 反射
              步骤:
                  1. 将需要创建的对象的全类名和需要执行的方法定义在配置文件中
                  2. 在程序中加载读取配置文件
                  3. 使用反射技术来加载类文件进内存
                  4. 创建对象
                  5. 执行方法
       */
      
      import java.io.InputStream;
      import java.lang.reflect.Method;
      import java.util.Properties;
      
      @Pro(className = "cn.xiaoge.day22.annotation.Demo1", methodName = "show")
      public class ReflectTest {
          /**
           *  框架类
           */
          public static void main(String[] args) throws Exception {
              // 可以创建任意类的对象, 可以执行任意方法
      
              /*
                  前提: 不能改变该类的任何代码, 可以创建任意类的对象, 可以执行任意方法
               */
      
              // 1. 解析注解
              // 1.1 获取该类的字节码文件对象
              Class<ReflectTest> reflectTestClass = ReflectTest.class;
      
              // 2. 获取上边的注解对象
              // 其实就是在内存中生成了一个该注解接口的子类实现对象
              Pro an = reflectTestClass.getAnnotation(Pro.class);
      
              // 3. 调用注解对象中定义的抽象方法, 获取返回值
              String className = an.className();
              String methodName = an.methodName();
      
              // System.out.println(className);  // cn.xiaoge.day22.annotation.Demo1
              // System.out.println(methodName); // show
      
              // 把该类加载进内存
              Class cls = reflectTestClass.forName(className);
      
              // 创建该类对象
              Object obj = cls.newInstance(); // 空参构造方法, 才可以这么调用, 有参构造, 必须先用getConstructor(类<?>... parameterTypes), 然后在newInstance
      
              // 获取该方法
              Method methodObj = cls.getMethod(methodName);
      
              // 执行该方法
              methodObj.invoke(obj);
      
          }
      
      }
      
      
      // 运行结果
      demo1...show...
      
  7. 案例

    1. 类Calculator
      package cn.xiaoge.day22.annotation.demo;
      
      /**
       *  定义计算器类
       */
      
      public class Calculator {
      
          // 加法
          @Check
          public void add(){
              System.out.println("1 + 0 = " + (1 + 0));
          }
      
          // 减法
          @Check
          public void sub(){
              System.out.println("1 - 0 = " + (1 - 0));
          }
      
          // 乘法
          @Check
          public void mul(){
              System.out.println("1 * 0 = " + (1 * 0));
          }
      
          // 除法
          @Check
          public void div(){
              System.out.println("1 / 0 = " + (1 / 0));
          }
      
          public void show(){
              System.out.println("永无bug....");
          }
      
      }
      
      
    2. 注解Check
      package cn.xiaoge.day22.annotation.demo;
      
      import java.lang.annotation.ElementType;
      import java.lang.annotation.Retention;
      import java.lang.annotation.RetentionPolicy;
      import java.lang.annotation.Target;
      
      @Retention(RetentionPolicy.RUNTIME) // 当前被描述的注解, 会保留到class字节码文件中, 并被JVM读取到
      @Target(ElementType.METHOD) // 可以作用于方法上
      public @interface Check {
      }
      
    3. TestCheck
      package cn.xiaoge.day22.annotation.demo;
      
      import java.io.BufferedWriter;
      import java.io.FileWriter;
      import java.io.IOException;
      import java.lang.reflect.Method;
      
      /**
       *  简单的测试框架
       *
       *  当主方法执行后, 会自动自行被检测的所有方法(加了Check注解的方法), 判断方法是否有异常, 记录到文件中
       *
       *
       *
       * 小结:
       * 	1. 以后大多数时候,我们会使用注解,而不是自定义注解
       * 	2. 注解给谁用?
       * 		1. 编译器
       * 		2. 给解析程序用
       * 	3. 注解不是程序的一部分,可以理解为注解就是一个标签
       *
       */
      
      public class TestCheck {
      
          public static void main(String[] args) throws IOException {
              // 1. 获取计算器对象
              Calculator c = new Calculator();
      
              // 2. 获取计算器字节码文件对象
              Class cls = c.getClass();
      
              // 3. 获取计算器所有的方法
              Method[] methods = cls.getMethods();
      
              int number = 0; // 出现异常的次数
      
              BufferedWriter bw = new BufferedWriter(new FileWriter("bug.txt"));
      
              for (Method method : methods) {
                  // 4. 判断方法是否有(Check)注解
                  if (method.isAnnotationPresent(Check.class)) {
                      try {
                          // 5. 有, 执行
                          method.invoke(c);
                      } catch (Exception e) {
                          // 6. 异常记录日志
      
                          // 记录到文件中
                          number++;
      
                          bw.write(method.getName() + "方法异常");
                          bw.newLine();
                          bw.write("异常的名称:" + e.getCause().getClass().getSimpleName());
                          bw.newLine();
                          bw.write("异常的原因:" + e.getMessage());
                          bw.newLine();
                          bw.write("-------------------------------");
                          bw.newLine();
                      }
                  }
              }
      
              bw.write("本次测试一共出现" + number + "次异常");
              bw.flush();
              bw.close();
      
      
      
          }
      
      }
      
      // 运行结果
      1 + 0 = 1
      1 - 0 = 1
      1 * 0 = 0 
      
    4. bug.txt
      div方法异常
      异常的名称:ArithmeticException
      异常的原因:null
      -------------------------------
      本次测试一共出现1次异常
      
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

只因为你温柔

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值