java8的新特性尝试

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.

  1. Declare a repeatable annotation type
  2. 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.

Java8ElementType枚举增加了TYPE_PARAMETERTYPE_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/

上一篇:JAVA8新api整理(一)


下一篇:java8 stream 对 list 对象集合进行模糊匹配