【JDK8新特性】注解

参考:
https://blog.csdn.net/sun_promise/article/details/51315032
https://docs.oracle.com/javase/tutorial/java/annotations/type_annotations.html
https://docs.oracle.com/javase/tutorial/java/annotations/repeating.html

类型注解(Type Annotations)

在JDK8之前,类型注解只能用在类型声明的地方:

@MyAnnotation  // 声明类
public class  Test {
}

JDK8后,类型注解可以在任何有类型的地方加入注解(包含泛型):

@MyAnnotation
public class Test<@MyAnnotation T> extends @MyAnnotation Fathers implements @MyAnnotation Callable {

    private @MyAnnotation String name = "lisi";

    public @MyAnnotation String test(@MyAnnotation String name) throws @MyAnnotation Exception {
        @MyAnnotation String s = "test";
        @MyAnnotation List<String> list = new @MyAnnotation ArrayList<>();
        Number a = 1;
        Integer i = (@MyAnnotation Integer) a;
        if (list.get(0) == null) {
            throw new @MyAnnotation Exception();
        }
        list.add(s);
        return list.get(0);
    }

    @Override
    public Object call() throws Exception {
        return null;
    }
}

作用

在8种新增类型注释主要是为了改进Java的程序分析,配合类型检查框架做强类型检查,从而在编译期间确认运行时异常,比如 NullpointException,从而提高代码质量。
比如:

@NonNull Object my = null;

第三方工具会在编译期间自动检测my是否为null,如果为null,抛出异常或者警告

目前具有此项功能的检测框架有 The Check Framework

创建类型注解

JDK8 新增ElementType.TYPE_USE用来创建类型注解:

@Target({TYPE_USE})
@Retention(RUNTIME)
public @interface MyAnnotation {
}

注意:JDK8还提供了 TYPE_PARAMETER 类型的注解,表示可以修饰类型参数(泛型)的注解。

可重复注解(Repeating Annotations)

在8之前,一个目标只可以打一个注解:

@Test
private String name;

现在JDK8提供了Repeating Annotations,可以在一个目标上打上多个可重复注解:

@Test("a")
@Test("b")
private String name;

创建可重复注解

JDK8中提供了一个新的源注解,用于表示可重复注解:

// 创建可重复注解:指定容器类型为 Sechedules.class
@Repeatable(Schedules.class)
@Retention(RetentionPolicy.RUNTIME)
public @interface Schedule {
    String dayOfMonth() default "first";
    String dayOfWeek() default "Mon";
    int hour() default 12;
}
// 可重复注解的容器注解,用于存放多个可重复注解: 
@Retention(RetentionPolicy.RUNTIME)
public @interface Schedules {
    Schedule[] value();
}

获取可重复注解

注意:如果想要在运行时获取注解,注解Retention必须为RetentionPolicy.RUNTIME,并且,Schedules与Schedule 注解的保留时期必须都为运行时!

获取可重复注解的方式同获取普通注解没有什么太大的区别:

@Schedule(hour = 9)
@Schedule(hour = 10)
public class Task {

    public static void main(String[] args) throws Exception {
        Schedule[] ats = Task.class.getAnnotationsByType(Schedule.class);
        System.out.println(Arrays.toString(ats));  
        // [@test.s.Schedule(hour=9, dayOfMonth=first, dayOfWeek=Mon), @test.s.Schedule(hour=10, dayOfMonth=first, dayOfWeek=Mon)]
        
        System.out.println(Arrays.toString(Task.class.getAnnotations())); 
        // [@test.s.Schedules(value=[@test.s.Schedule(hour=9, dayOfMonth=first, dayOfWeek=Mon), @test.s.Schedule(hour=10, dayOfMonth=first, dayOfWeek=Mon)])]
        //注意:这里获取到的是 Schedules 注解,而不是多个 Schedule 注解
    }
}

可重复注解的原理

使用一个注解来存储重复的注解,编译后的class为:

@Schedules({@Schedule(hour = 9), @Schedule(hour = 10)})
public class Task {
    public Task() {
    }
    public static void main(String[] args) throws Exception {
        Schedule[] ats = (Schedule[])Task.class.getAnnotationsByType(Schedule.class);
        System.out.println(Arrays.toString(ats));
        System.out.println(Arrays.toString(Task.class.getAnnotations()));
    }
}

所谓的可重复注解,只是编译层面的改动

你可能感兴趣的:(Java)