1. 优享JAVA首页
  2. Java
  3. 注解

Java注解基本介绍 二

为了处理上述的新增注解,Java8还在AnnotatedElement接口新增了getDeclaredAnnotationsByType() 和 getAnnotationsByType()两个方法并在接口给出了默认实现

在指定@Repeatable的注解时,可以通过这两个方法获取到注解相关信息。

这里我们需要注意的是旧版API中的getDeclaredAnnotation()和 getAnnotation()是不对@Repeatable注解的处理的(除非该注解没有在同一个声明上重复出现)。

注意getDeclaredAnnotationsByType方法获取到的注解不包括父类,其实当 getAnnotationsByType()方法调用时,其内部先执行了getDeclaredAnnotationsByType方法

只有当前类不存在指定注解时,getAnnotationsByType()才会继续从其父类寻找,但请注意如果@FilterPath和@FilterPaths没有使用了@Inherited的话,仍然无法获取。

下面是示例代码:

import java.lang.annotation.*;

@Target({ElementType.TYPE,ElementType.FIELD,ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Inherited //添加可继承元注解
@Repeatable(FilterPaths.class) // 参数指定接收的class
public @interface FilterPath{
    String  value();
}

@Target(ElementType.TYPE)
@Inherited //添加可继承元注解
@Retention(RetentionPolicy.RUNTIME)
@interface FilterPaths {
    FilterPath[] value();
}

@FilterPath("/test1/1")
@FilterPath("/test1/2")
@FilterPath("/test1/3")
class Test1{ }

//只有在子类没有使用@FilterPath注解的时候,getAnnotationsByType()方法才会从父类中找@FilterPath,反之则不会
//@FilterPath("/test2/1")
//@FilterPath("/test2/2")
//@FilterPath("/test2/3")
class Test2 extends Test1 {
    public static void main(String[] args) {
        Class<?> clazz = Test2.class;
        //通过getAnnotationsByType方法获取所有重复注解
        FilterPath[] annotationsByType = clazz.getAnnotationsByType(FilterPath.class);
        FilterPath[] annotationsByType2 = clazz.getDeclaredAnnotationsByType(FilterPath.class);
        if (annotationsByType != null) {
            for (FilterPath filter : annotationsByType) {
                System.out.println("1:"+filter.value());
            }
        }
        System.out.println("-----------------");
        if (annotationsByType2 != null) {
            for (FilterPath filter : annotationsByType2) {
                System.out.println("2:"+filter.value());
            }
        }
        System.out.println("使用getAnnotation的结果:"+clazz.getAnnotation(FilterPath.class));

    }
}
 /**
  * 运行结果如下:
  *
  * 1:/test1/1
  * 1:/test1/2
  * 1:/test1/3
  * -----------------
  * 使用getAnnotation的结果:null
  */

Java 8 新增的注解类型

在Java 8中 ElementType 新增两个枚举成员,TYPE_PARAMETER 和 TYPE_USE ,在Java 8前注解只能标注在一个声明(如字段、类、方法)上,Java 8后,新增的TYPE_PARAMETER可以用于标注类型参数,而TYPE_USE则可以用于标注任意类型(不包括class)

如下所示

//TYPE_PARAMETER 标注在类型参数上 
class D<@Parameter T> { } 

//TYPE_USE则可以用于标注任意类型(不包括class) 
//用于父类或者接口 
class Image implements @Rectangular Shape { } 

//用于构造函数 
new @Path String("/usr/bin") 

//用于强制转换和instanceof检查,注意这些注解中用于外部工具,它们不会对类型转换或者instanceof的检查行为带来任何影响。 
String path=(@Path String)input; if(input instanceof @Path String) 

//用于指定异常 
public Person read() throws @Localized IOException. 

//用于通配符绑定
List<@ReadOnly ? extends Person> 
List<? extends @ReadOnly Person> 

@NotNull String.class 
//非法,不能标注

class import java.lang.@NotNull String 
//非法,不能标注import

这里主要说明一下TYPE_USE,类型注解用来支持在Java的程序中做强类型检查,配合第三方插件工具,可以在编译期检测出runtime error(如UnsupportedOperationException、NullPointerException异常),避免异常延续到运行期才发现,从而提高代码质量,这就是类型注解的主要作用。

总结,Java 8中新增加了两个注解的元素类型ElementType.TYPE_USE 和ElementType.TYPE_PARAMETER ,通过它们,我们可以把注解应用到各种新场合中。

原创文章,作者:Craig,如若转载,请注明出处:https://www.goodlymoon.com/archives/1586.html

发表评论

电子邮件地址不会被公开。 必填项已用*标注

QR code