什么是元注解 元注解有哪些 元注解是干什么的 注解用什么修饰

元注解的作用就是负责注解其他注解,元注解有以下6种

  • @Retention:指定其所修饰的注解的保留策略
  • @Document:该注解是一个标记注解,用于指示一个注解将被文档化
  • @Target:用来限制注解的使用范围
  • @Inherited:该注解使父类的注解能被其子类继承
  • @Repeatable:该注解是Java8新增的注解,用于开发重复注解
  • 类型注解(Type Annotation):该注解是Java8新增的注解,可以用在任何用到类型的地方

@Retention注解

 @Retention注解注解用于指定被修饰的注解可以保留多长时间,即指定JVM策略在哪个时间点上删除当前注解。保留策略值有以下三个:

注解保留策略值
策略值功能描述
Retention.SOURCE注解只在源文件中保留,在编译期间删除
Retention.CLASS注解只在编译期间存在于.class文件中,运行时JVM不可获取注解信息,该策略值也是默认值
Retention.RUNTIME运行时JVM可以获取注解信息(反射),是最长注解持续期

【示例】运行时JVM可以获取注解信息

@Retention(RetentionPolicy.RUNTIME)
//定义注解

@Document注解

@Document注解用于指定被修饰的注解可以被javadoc工具提取成文档。定义注解类时使用@Document注解进行修饰,则所有使用该注解修饰的程序元素的API文档中将会包含该注解说明。

@Document
//定义注解

 @Target注解

@Target注解用来限制注解的使用范围,即指定被修饰的注解能用于哪些程序单元

@Target({应用类型1, 应用类型2,...})
ElementType枚举值
枚举值功能描述
ElementType.Type可以修饰类、接口、注解或枚举类型
ElementType.FIELD可以修饰属性(成员变量),包括枚举常量
ElementType.METHOD可以修饰方法
ElementType.PAPAMETER可以修饰参数
ElementType.CONSTRUCTOR可以修饰构造方法
ElementType.LOCAL_VARIABLE可以修饰局部变量
ElementType.ANNOTATION_TYPE可以修饰注解类
ElementType.PACKAGE可以修饰包

【示例】指定注解只能修饰字段

@Target(ElementType.FIELD)
//定义注解

@Inherited注解

@Inherited注解指定注解具有继承性,如果某个注解使用@Inherited进行修饰,则该类使用该注解时,其子类将自动被修饰

【示例】

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Inherited
public @interface InheritedAnno1 {
    String comment();
    int order() default 1;
}
//使用自定义的@InheritedAnno1注解修饰Base
@InheritedAnno1(comment = "继承注解", order = 2)
class Base{

}
//InheritedDemo只继承了Base类
//并未直接使用@InheritedAnno1注解
public class InheritedDemo extends Base{
    public static void main(String[] args) {
        //从InheritedDemo中获取InheritedAnno1注解信息
        InheritedAnno1 anno = InheritedDemo.class.getAnnotation(InheritedAnno1.class);
        //输出InheritedAnno1注解成员信息
        System.out.println(anno.comment()+":"+anno.order());
        //打印InheritedDemo类是否具有@InheritedAnno1修饰
        System.out.println(InheritedDemo.class.isAnnotationPresent(InheritedAnno1.class));
    }
}

运行结果:

 @Repeatable注解

@Repeatable注解是Java8新增的注解,用于开发重复注解。在Java8之前,同一个程序元素前只能使用一个相同类型的注解,如果需要在同一个元素前使用多个相同类型的注解必须通过注解容器来实现。从Java8开始,允许使用多个相同的类型注解来修饰同一个元素,前提是该类型的注解是可重复的,即在定义注解时要用 @Repeatable元注解进行修饰。

【示例】

import java.lang.annotation.*;

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@interface AnnolContents{//该注解是容器
    //定义value成员变量,该成员变量可以接受多个@RepeatableAnnol注解
    RepeatableAnnol[] value();
}

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Repeatable(AnnolContents.class)
public @interface RepeatableAnnol {
    String name() default "南瓜仔仔";
    int age();
}
@RepeatableAnnol(age = 10)
@RepeatableAnnol(name = "寻找南瓜", age = 22)
public class RepeatableAnnolDemo {
    public static void main(String[] args) {
        //使用java8新增的getDeclaredAnnotationsByType()方法获取
        //修饰类的多个@RepeatableAnnol注解
        RepeatableAnnol[] annols = RepeatableAnnolDemo.class.getDeclaredAnnotationsByType(RepeatableAnnol.class);
        //遍历@RepeatableAnnol注解并显示
        for (RepeatableAnnol annol :annols){
            System.out.println(annol.name() + "--->" + annol.age());
        }
        //使用传统的getDeclaredAnnotation()方法获取修饰类的@AnnolContents注解
        AnnolContents container = RepeatableAnnolDemo.class.getDeclaredAnnotation(AnnolContents.class);
        System.out.println(container);
    }
}

运行结果:

南瓜仔仔--->10
寻找南瓜--->22
@com.ngd.test03.AnnolContents({@com.ngd.test03.RepeatableAnnol(name="\u5357\u74dc\u4ed4\u4ed4", age=10), @com.ngd.test03.RepeatableAnnol(name="\u5bfb\u627e\u5357\u74dc", age=22)})

 类型注解

Java8为ElementType枚举增加了TYPE_PARAMETER和TYPE_USE两个枚举类值,允许在定义枚举类时使用@Target(ElementType.TYPE_USE)来修饰,此种注解被称为“类型注解”(Type Annotation)。

在Java8之前,只能在定义类、接口、方法和成员变量等程序元素时使用注解,从Java8开始新增的类型注解可以用在任何用到类型的地方。

除了在定义类接口方法等常见的程序元素时可以使用类型注解,还可以在以下几个位置使用类型注解进行修饰:

  • 创建对象(使用new关键字创建)
  • 类型转换
  • 使用implements实现接口
  • 使用throws声明抛出异常序列
  • 方法参数
//定义一个简单的类型注解,不带任何成员变量
@Target(ElementType.TYPE_USE)
@interface NotNull{
}

//定义类时使用@NotNull类型注解
@NotNull
public class TypeAnnotationDemo implements @NotNull Serializable {//implements时使用类型注解
    //方法形参中使用类型注解
    public static void main(@NotNull String[] args) throws @NotNull FileNotFoundException {//throws使用时用类型注解
        Object obj = "南瓜仔仔";
        //强制类型转换时使用类型注解
        String str = (@NotNull String)obj;
        //创建对象时使用类型注解
        Object win = new @NotNull JFrame("QST_Login");
    }
    //泛型中使用类型注解
    public void foo(List<@NotNull String> info){}
}

上述代码在各种情况下使用@ NotNull 类型注解,这种无处不在的类型注解可以让编译器执行更严格的代码检查,从而提高程序的健壮性。需要说明的是,上面的程序虽然大量使用了@ NotNull 类型注解,但这些注解是不会起到任何作用的,因为 Java 8本身并没有为这些类型注解提供处理工具,不能对类型注解执行检查框架。因此,如果需要类型注解发挥作用,需要程序员自己实现类型注解检查框架。目前有些第三方组织发布了类型注解检查工具,程序员可以直接使用这些第三方框架提供的检查工具,从而让编译器执行更严格的检查,以保证代码的健壮性。

  • 7
    点赞
  • 38
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值