java8新特性之注解增强

Posted by Chris on August 18, 2019

java8对注解的功能进行了增强,主要体现在两方面:

1)可以添加重复注解;

2)可以为任何目标添加注解

假设注解为

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface Author {
    String name() default "";
}

添加重复注解

@Author(name = "chris")
@Author(name = "bob")  // 编译会报错,因为有重复使用注解
public class AnnotationDemo {

}

为了绕过无法添加多个注解的限制,可以再定义一个注解,属性为一个数组。如下面的代码所示。

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@interface Authors {
    Author[] value();
}

@Authors(value = {
        @Author(name = "chris"),
        @Author(name = "bob")
})
public class AnnotationDemo {
}

这样的方式使用起来还是有些不方便的。

java8提供了语法糖的形式,方便开发者使用。

如何创建一个重复注解

@Repeatable(Authors.class) 
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@interface Author {
    String name();
}

@interface Authors {
    Author[] value();
}

这里仍然需要定义两个注解@Author 和 @Authors。 其中,希望重复使用的注解@Author 带有 @Repeatable注解,里面的属性值的意思是,哪个注解含有 @Author 数组。

如何使用重复注解

@Author(name = "chris")
@Author(name = "bob")
public class AnnotationDemo {

}

像上面的使用方式,就比较符合开发者的使用习惯了。

编译时,AnnotationDemo会被认为使用了

@Authors(value = {
        @Author(name = "chris"),
        @Author(name = "bob")
})

如何通过反射获取重复注解

通过方法 getAnnotationsByType(Class< A> annotationClass)可以获取到重复注解,该方法从Java8开始提供。

@Author(name = "chris")
@Author(name = "bob")
public class AnnotationDemo {
    public static void main(String[] args) {
        Author[] annotations = AnnotationDemo.class.getAnnotationsByType(Author.class);
        Arrays.asList(annotations).forEach(a -> System.out.println(a.name()));
    }
}

为任何目标添加注解

从java8开始,注解可以用于任何目标了,除了之前支持的类型,方法,字段等,还支持包括new操作符、类型转换、instanceof检查、泛型类型参数,以及implements和throws子句。

比如,为返回的字段判空的注解。

@NonNull String name = person.getName();

那么,我们就可以对自定义一个注解@NonNull,对@NonNull添加的字段,执行判空逻辑。注意,java8只是提供了为任何目标类添加注解的功能,注解具体的实现逻辑,还是需要开发者自己实现。

参考