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只是提供了为任何目标类添加注解的功能,注解具体的实现逻辑,还是需要开发者自己实现。