注解

1. 注解的概念

注解(Annotation),也叫元数据。它可以声明在包、类、字段、方法、局部变量、方法参数等的前面,用来对这些元素进行说明,注释。

2. 注解的作用

  • 编写文档:通过代码里标识的注解生成 doc 文档
  • 编译检查:通过代码里标识的注解让编译器能够实现基本的编译检查
  • 代码分析:通过代码里标识的注解对代码进行分析

3. JDK 内置注解

  • @Override:检测该注解标注的方法是否继承自父类(接口)

  • @Deprecated:该注解标注的内容,表示已过时

  • @SuppressWarnings:压制警告

    如:@SuppressWarnings(“all”):压制所有警告

4. 自定义注解

4.1 注解的格式

元注解
public @interface 注解名称{
	属性列表;
}

4.2 注解的本质

  1. 自定义一个注解,如下:

    public @interface 注解名称 {   
    }
    
  2. 将这个注解先进行编译,再将其反编译,得到如下代码:

    public interface 注解名称 extends java.lang.annotation.Annotation {
    }
    
  3. 于是得出结论:注解本质上就是一个接口,该接口默认继承Annotation接口。

4.3 注解的属性

由注解的格式我们可以知道,注解由元注解接口两部分组成。

注解的属性就是接口中的方法。

使用注解时,有以下要求:

  • 属性的返回值类型只能是以下几种:
    • 基本数据类型
    • String
    • 枚举
    • 注解
    • 以上类型的数组
  • 定义了属性,在使用时需要给属性赋值
    • 如果定义属性时,使用 default 关键字给属性默认初始化值,则使用注解时,可以不进行属性的赋值。
    • 如果只有一个属性需要赋值,并且属性的名称是 value,则 value 可以省略,直接定义值即可。
    • 数组赋值时,值使用 {} 包裹。如果数组中只有一个值,则 {} 可以省略。

4.4 元注解

元注解是用于描述注解的注解

以下是常用的元注解:

  • @Target:描述注解能够作用的位置
    • ElementType.TYPE:可以作用于类上
    • ElementType.METHOD:可以作用于方法上
    • ElementType.FIELD:可以作用于成员变量上
  • @Retention:描述注解被保留的阶段
    • RetentionPolicy.SOURCE:当前被描述的注解,会被编译器弃用
    • RetentionPolicy.CLASS:当前被描述的注解,会保留到class字节码文件中
    • RetentionPolicy.RUNTIME:当前被描述的注解,会保留到class字节码文件中,并被 JVM 读取到(自定义的注解一般使用这个)
  • @Documented:描述注解是否被抽取到 API 文档中
  • @Inherited:描述注解是否被子类继承

5. 使用自定义注解

  1. 获取注解定义位置(Class,Method,Field)的对象

  2. 由对象获取指定的注解

    对象名.getAnnotation(注解名.Class)

  3. 调用注解中的抽象方法获取属性值

6. 注解的案例

  1. 需求分析

    写一个“框架",在不改变该类的任何代码的前提下,可以帮我们创建任意类的对象,并且执行其中任意方法。

  2. 概要设计

    在类的前面声明自定义注解,并给属性赋予全类名和方法名,然后在类中使用注解获取属性值,然后加载该类进内存,之后创建对象,再利用反射获取需要执行的方法,最后执行方法。

  3. 详细设计

    1. 创建自定义注解 @pro,其中有属性:className(),methodName()
    2. 在测试类的前面添加自定义注解 @pro 并赋值
    3. 使用注解获取属性值
    4. 根据全类名加载该类进内存,获取对应的 Class 对象
    5. 创建对象
    6. 利用反射获取需要执行的方法
    7. 执行该方法
  4. 编码实现

    • @pro

      /**
       * 描述需要执行的类名,方法名
       */
      @Target({ElementType.TYPE})
      @Retention(RetentionPolicy.RUNTIME)
      public @interface pro {
          String className();
          String methodName();
      }
      
    • AnnotationTest

      @pro(className = "com.zt.annotation.Student",methodName = "study")
      public class AnnotationTest {
          public static void main(String[] args) throws Exception {
              //1. 使用注解
              //1.1 获取该类的类对象
              Class<AnnotationTest> reflectTestClass = AnnotationTest.class;
              //1.2 获取上边的注解对象
              // 其实就是在内存中生成了一个该注解接口的子类实现对象
              pro annotation = reflectTestClass.getAnnotation(pro.class);
              //1.3 调用注解对象中的抽象方法,获取返回值
              String className = annotation.className();
              String methodName = annotation.methodName();
      
      
              //2. 根据全类名加载该类进内存,获取对应的 Class 对象
              Class<?> aClass = Class.forName(className);
      
              //3. 创建对象
              Object o = aClass.newInstance();
      
              //4. 利用反射获取方法
              Method method1 = aClass.getMethod(methodName);
      
              //5. 执行该方法
              method1.invoke(o);
          }
      }
      
      
    • 执行结果

      study...
      
      Process finished with exit code 0
      
      
  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

bm1998

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

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

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

打赏作者

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

抵扣说明:

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

余额充值