2021-06-20

自定义注解

注解定义的关键字:@interface

自定义注解中的成员属性

  • 修饰符 数据类型 属性名(); public abstract
  • 数据类型的要求:
    • 可以是所有的基本数据类型
    • 可以是字符串类型
    • 可以是枚举类型
    • 可以是Class类
    • 可以是其它的注解类型
    • 或者是以上类型的一维数组
public @interface MyAnnotation {
    //定义注解的属性
    String name ();//字符串类型

    int age(); //基本类型int

    Color color();//枚举类型

    Class clazz();//Class类型
    
    String[] value();//字符串数组
}

注解的属性赋值

  • @注解名(属性=值,属性=值)
@Book(name = "红楼梦",price = 50.99,jieShao = "金陵十二钗",author = {"曹雪芹","高鹗"})
public void sellBook(){
}
  • 注解中有默认值,可以不用赋值
//页数,默认值200
int page() default 200;
@Book(page = 300,name = "红楼梦",price = 50.99,jieShao = "金陵十二钗",author = {"曹雪芹","高鹗"})
public void sellBook(){

}
  • 注解中的属性只有一个,属性值必须是value,可以不写属性名
  • 如果是一个数组,数组中的元素只有一个,可以不写{}
@NewsPaper({"新闻早知道","新闻晚知道","新闻不知道"})
public void sellNewPaper(){

}

注解赋值的注意事项:一个注解,在一个对象上只能使用一次

注解解析

获取注解中的属性值,注解解析必须使用反射

public class CarStore {
    @Car(name = "比亚迪",price = 89999)
    public void sellCar(){

    }
}

反射方法sellCar(),获取方法上的注解

  • Method类,表示成员方法对象,类实现接口AnnotatedElement

  • 接口中的方法:isAnnotationPresent(Class c)判断方法上是否有注解,有注解返回true,没有注解返回false.

    • 参数Class对象,传递注解的class文件对象
  • /**
      * 反射获取方法上的注解
      */
     @Test
     public void testAnnotation()throws Exception{
         Class clazz = Class.forName("com.atguigu.annotation.CarStore");
         //反射获取方法sellCar
         Method method =  clazz.getMethod("sellCar");
         System.out.println("method = " + method);
         //接口中的方法:isAnnotationPresent(Class c)判断方法上是否有注解,
         // 有注解返回true,没有注解返回false.
         boolean b = method.isAnnotationPresent(Car.class);
         System.out.println("b = " + b);
         //接口方法,获取注解
         Car car = method.getAnnotation(Car.class);
         //获取注解的属性
         String name = car.name();
         double price = car.price();
         System.out.println("name = " + name);
         System.out.println("price = " + price);
     }
    

    接口中的方法:getAnnotation(Class对象)获取注解

元注解

JDK内置了2个元注解

  • @Target注解:明确其它注解可以出现的位置
    • 不是用该注解,我们自定义的注解@Car,可以出现在一个类的任意位置上
    • @Target控制我们自己的注解
    • @Target注解的属性是value,数据类型ElementType
    • ElementType是枚举:静态成员
    • TYPE,METHOD,FIELD指示我们的注解,可以出现在类上,方法上,成员变量上
//使用元注解,Car注解出现在方法上,类上
@Target(value = {ElementType.METHOD,ElementType.TYPE})
public @interface Car {
    String name();
    double price();
}
  • @Retention注解:明确其它注解生存的时间
    • 注解属性是value,数据类型RetentionPolicy
    • RetentionPolicy是枚举:
    • SOURCE,CLASS,RUNTIME 当前的注解存在时间,源码中,class文件中,运行的内存中
      • SOURCE:当我们将java代码编译成class文件时,该注解被遗弃
      • CLASS:默认的,注解保留在class文件中,当jvm把class文件加载到内存中时被遗弃
      • RUNTIME:注解不仅能保存在class文件中,也能保存在内存中
//SOURCE 我们的Override就是使用这个,在编译期间生效

//使用元注解,Car注解出现在方法上,类上
@Target(value = {ElementType.METHOD,ElementType.TYPE})
//使用 元注解,Car注解,生存到内存中
@Retention(value = RetentionPolicy.RUNTIME)
public @interface Car {
    String name();
    double price();
}

上一篇:QSS 样式表语法


下一篇:5G系统概念 | 《5G移动无线通信技术》之七