注解

一、创建注解

1、注解的基本概念
从JDK5开始,Java增加对元数据的支持,也就是注解,注解与注释是有一定区别的,可以把注解理解为代码里的特殊标记,这些标记可以在编译,类加载,运行时被读取,并执行相应的处理。通过注解,开发人员可以在不改变原有代码和逻辑的情况下在源代码中嵌入补充信息。
2、注解的语法格式

访问修饰符 @interface 注解名称{
    注解成员;
  }

自定义注解自动继承java.lang.annotation.Annotation接口。

3、一个简单的注解的例子

public @interface Report {
    int type() default 0;//属性名:type 类型是int 默认值是0
    String level() default "info"; //属性名:level 类型String   默认值“info”
    String value() default ""; //属性名:value  类型 String 默认值“”
}

4、注解体的中成员的定义

  • 注解体中只有成员变量没有成员方法,而注解的成员变量以“无形参的方法”形式来声明,其方法名定义了该成员变量的名字,其返回值定义了该成员变量的类型。

  • 如果注解只有一个参数成员,建议使用参数名为value,而类型只能是八种基本数据类型、String类型、Class类型、enum类型及Annotation类型。

  • 使用default关键字声明默认值
    5、元注解

有一些注解可以修饰其他注解,这些注解就称为元注解(meta annotation)。Java标准库已经定义了一些元注解,我们只需要使用元注解,通常不需要自己去编写元注解。

@Target

最常用的元注解是@Target。使用@Target可以定义Annotation能够被应用于源码的哪些位置:

  • 类或接口:ElementType.TYPE
  • 字段:ElementType.FIELD
  • 方法:ElementType.METHOD
  • 构造方法:ElementType.CONSTRUCTOR
  • 方法参数:ElementType.PARAMETER
@Target(ElementType.METHOD)
public @interface Report {
    int type() default 0;
    String level() default "info";
    String value() default "";
}

使用@Target注解

@Report(level = "debug",type = 1,value = "woniu") //使用注解并且改变默认值
public void print(){

	System.out.print("targer 注解使用");
}
@Retention

另一个重要的元注解@Retention定义了Annotation的生命周期:

  • 仅编译期:RetentionPolicy.SOURCE
  • 仅class文件:RetentionPolicy.CLASS
  • 运行期:RetentionPolicy.RUNTIME

如果@Retention不存在,则该Annotation默认为CLASS。因为通常我们自定义的Annotation都是RUNTIME,所以,务必要加上@Retention(RetentionPolicy.RUNTIME)这个元注解:

@Retention(RetentionPolicy.RUNTIME)
public @interface Report {
    int type() default 0;
    String level() default "info";
    String value() default "";
}
@Repeatable

使用@Repeatable这个元注解可以定义Annotation是否可重复。这个注解应用不是特别广泛。

在@Repeatable后面的括号里面我们标注Reports.class,意思是在使用多个@Report注解的时候,这些注解被放在了Reports类型的注解中,参见下面的定义:我们在Reports这个注解中定义了一个数组Report[] value();这个Report[]数据就是用来存放多个@Report注解的。

@Repeatable(Reports.class)
@Target(ElementType.TYPE)
public @interface Report {
    int type() default 0;
    String level() default "info";
    String value() default "";
}

@Target(ElementType.TYPE)
public @interface Reports {
    Report[] value();
}

经过@Repeatable修饰后,在某个类型声明处,就可以添加多个@Report注解:

@Report(type=1, level="debug")
@Report(type=2, level="warning")
public class Hello {
}
@Inherited

使用@Inherited定义子类是否可继承父类定义的Annotation@Inherited仅针对@Target(ElementType.TYPE)类型的annotation有效,并且仅针对class的继承,对interface的继承无效:

@Inherited
@Target(ElementType.TYPE)
public @interface Report {
    int type() default 0;
    String level() default "info";
    String value() default "";
}

在使用的时候,如果一个类用到了@Report

@Report(type=1)
public class Person {
}

则它的子类默认也定义了该注解:

public class Student extends Person {
}

二、反射获取Annotation信息

创建一个工程

image-20210606215318321

定义@Report注解

@Inherited
@Target({ElementType.TYPE,ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Repeatable(Reports.class)
public @interface Report {
    int type() default 0;
    String level() default "info";
    String value() default "";
}

定义@Reports注解



@Inherited //可以继承
@Target({ElementType.TYPE,ElementType.METHOD})//可以修饰类或接口和方法
@Retention(RetentionPolicy.RUNTIME)//运行期存在
public @interface Reports {
    Report[] value();
}

定义一个Dog类,使用@Report注解

@Report(type=1,value = "jinmao",level = "abc")
@Report(type=2,value = "bianmu")
public class Dog {

    @Report
    public void print(){
        System.out.println("测试");
    }

    public void hello(){
        System.out.println("hello");
    }

}

定义一个Parent类

@Report
public class Parent {

}

定义一个Son类

public class Son extends Parent{
}

定义一个Test类运行

public class Test {

    public static void main(String[] args) throws IllegalAccessException, InstantiationException, InvocationTargetException {
        //1.获取到Class实例
        Class<Dog> dogClass = Dog.class;

        //判断类上是否有report的集合
        boolean present = dogClass.isAnnotationPresent(Reports.class);
        if(present){
            //获取Dog类上面的Reports注解
            Reports reports = dogClass.getAnnotation(Reports.class);
            //循环打印出注解上的属性值
            for (Report report : reports.value()) {
                System.out.println(report.type()+":"+report.level()+":"+report.value());

            }
        }
        Dog dog = dogClass.newInstance();
        //获取类的所有方法
        Method[] methods = dogClass.getDeclaredMethods();
        for (Method method : methods) {
            //如果方法被@Report注解修饰,执行它
            if (method.isAnnotationPresent(Report.class)) {
                method.invoke(dog,null);
            }
        }

        //测试一下继承的注解
        Class<Son> sonClass = Son.class;
        //判断son是否继承了Parent的注解@Report
        if (sonClass.isAnnotationPresent(Report.class)) {
            System.out.println("son 从  parent继承了@Report注解");
        }
    }

}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值