Java Repeating Annotations
In Java 8 release, Java allows you to repeating annotations in your source code. It is helpful when you want to reuse annotation for the same class. You can repeat an annotation anywhere that you would use a standard annotation.
For compatibility reasons, repeating annotations are stored in a container annotation that is automatically generated by the Java compiler. In order for the compiler to do this, two declarations are required in your code.
- Declare a repeatable annotation type
- Declare the containing annotation type
1) Declare a repeatable annotation type
Declaring of repeatable annotation type must be marked with the @Repeatable meta-annotation. In the following example, we have defined a custom @Game repeatable annotation type.
@Repeatable(Games.class)
@interfaceGame{
String name();
String day();
}
The value of the @Repeatable meta-annotation, in parentheses, is the type of the container annotation that the Java compiler generates to store repeating annotations. In the following example, the containing annotation type is Games. So, repeating @Game annotations is stored in an @Games annotation.
2) Declare the containing annotation type
Containing annotation type must have a value element with an array type. The component type of the array type must be the repeatable annotation type. In the following example, we are declaring Games containing annotation type:
@interfaceGames{
Game[] value();
}
Note - Compiler will throw a compile-time error, if you apply the same annotation to a declaration without first declaring it as repeatable.
Java Repeating Annotations Example
// Importing required packages for repeating annotation
import java.lang.annotation.Repeatable;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
// Declaring repeatable annotation type
@Repeatable(Games.class)
@interfaceGame{
String name();
String day();
}
// Declaring container for repeatable annotation type
@Retention(RetentionPolicy.RUNTIME)
@interfaceGames{
Game[] value();
}
// Repeating annotation
@Game(name = "Cricket", day = "Sunday")
@Game(name = "Hockey", day = "Friday")
@Game(name = "Football", day = "Saturday")
public class RepeatingAnnotationsExample {
public static void main(String[] args) {
// Getting annotation by type into an array
Game[] game = RepeatingAnnotationsExample.class.getAnnotationsByType(Game.class);
for (Gamegame2 : game) { // Iterating values
System.out.println(game2.name()+" on "+game2.day());
}
}
}
OUTPUT:
Cricket on Sunday
Hockey on Friday
Football on Saturday
Java Type Annotations
Java 8 has included two new features repeating and type annotations in its prior annotations topic. In early Java versions, you can apply annotations only to declarations. After releasing of Java SE 8 , annotations can be applied to any type use. It means that annotations can be used anywhere you use a type. For example, if you want to avoid NullPointerException in your code, you can declare a string variable like this:
@NonNull String str;
Following are the examples of type annotations:
@NonNull List<String>
List<@NonNull String> str
Arrays<@NonNegative Integer> sort
@Encrypted File file
@Open Connection connection
void divideInteger(int a, int b) throws @ZeroDivisor ArithmeticException
Note - Java created type annotations to support improved analysis of Java programs. It supports way of ensuring stronger type checking.
Java8
为ElementType
枚举增加了TYPE_PARAMETER
、TYPE_USE
两个枚举值,这样就允许定义枚举时使用@Target(ElementType.TYPE_USE
)修饰,这种注解被称为类型注解(Type Annotation
),类型注解可用于修饰在任何地方出现的类型。
Java 8为增加的ElementType 枚举值 |
描述 |
---|---|
TYPE_PARAMETER |
Type parameter declaration |
TYPE_USE |
Use of a type |
在Java8
以前,只能在定义各种程序元素(定义类、定义接口、定义方法、定义成员变量……)时使用注解。从Java8
开始,类型注解可以修饰在任何地方出现的类型。比如,允许在如下位置使用类型注解。
- 创建对象(用
new
关键字创建) - 类型转换。
- 使用
implements
实现接口 - 使用
throws
声明抛出异常。
上面这些情形都会用到类型,因此都可以使用类型注解来修饰。
下面程序将会定义一个简单的类型注解,然后就可在任何用到类型的地方使用类型注解了,读者可通过该示例了解类型注解无处不在的神奇魔力。
import java.util.*;
import java.io.*;
import javax.swing.*;
import java.lang.annotation.*;
// 定义一个简单的类型注解,不带任何成员变量
@Target(ElementType.TYPE_USE)
@interface NotNull {
}
// 定义类时使用类型注解
@NotNull
public class TypeAnnotationTest implements @NotNull /* implements时使用类型注解 */ Serializable {
// 方法形参中使用类型注解
public static void main(@NotNull String[] args)
// throws时使用类型注解
throws @NotNull FileNotFoundException {
Object obj = "fkjava.org";
// 强制类型转换时使用类型注解
String str = (@NotNull String) obj;
// 创建对象时使用类型注解
Object win = new @NotNull JFrame("疯狂软件");
}
// 泛型中使用类型注解
public void foo(List<@NotNull String> info) {
}
}
上面的程序中都是可正常使用类型注解的例子,从这个示例可以看到,Java
程序到处“写满”了类型注解,这种“无处不在”的类型注解可以让编译器执行更严格的代码检查,从而提高程序的健壮性
需要指出的是,上面程序虽然大量使用了@NotNull
注解,但这些注解暂时不会起任何作用——因为并没有为这些注解提供处理工具。而且Java8
本身并没有提供对类型注解执行检査的框架,因此如果需要让这些类型注解发挥作用,开发者需要自己实现类型注解检査框架
幸运的是,Java8
提供了类型注解之后,第三方组织在发布他们的框架时,可能会随着框架一起发布类型注解检査工具,这样普通开发者即可直接使用第三方框架提供的类型注解,从而让编译器执行更严格的检查,保证代码更加健壮。
参考文章
1、https://www.javatpoint.com/java-8-type-annotations-and-repeating-annotations
2、https://lanlan2017.github.io/JavaReadingNotes/dc18e9d7/