一.重复注解

在某些情况下,希望将相同的注解应用于声明或类型用途。从Java SE 8发行版开始,重复注解使可以执行此操作。

例如,正在编写代码以使用计时器服务,该服务使能够在给定时间或某个计划上运行方法,类似于UNIX cron服务。现在,要设置计时器以在该月的最后一天和每个星期五晚上11:00 运行方法doPeriodicCleanup。要设置要运行的计时器,请创建一个@Schedule注解并将其应用于doPeriodicCleanup方法两次。第一次使用指定月份的最后一天,第二次使用指定星期五晚上11点,如下面的代码示例所示:

@Schedule(dayOfMonth="last")
@Schedule(dayOfWeek="Fri", hour="23")
public void doPeriodicCleanup() { ... }

前面的示例将注解应用于方法。可以在使用标准注解的任何位置重复注解。例如,有一个用于处理未授权访问异常的类。使用一个@Alert注解为管理员注解并为管理员添加另一个注解:

@Alert(role="Manager")
@Alert(role="Administrator")
public class UnauthorizedAccessException extends SecurityException { ... }

出于兼容性原因,重复注解存储在由Java编译器自动生成的容器注解中。为了使编译器执行此操作,代码中需要两个声明。

第1步:声明可重复的注解类型

注解类型必须使用@Repeatable元注解标记。以下示例定义自定义@Schedule可重复注解类型:

import java.lang.annotation.Repeatable;

@Repeatable(Schedules.class)
public @interface Schedule {
String dayOfMonth() default "first";
String dayOfWeek() default "Mon";
int hour() default 12;
}

@Repeatable括号 中的元注解的值是Java编译器为存储重复注解而生成的容器注解的类型。在此示例中,包含注解类型是Schedules,因此重复@Schedule注解存储在@Schedules注解中。

将相同的注解应用于声明而不首先声明它是可重复的,这会导致编译时错误。

第2步:声明包含注解类型

包含注解类型必须具有value带数组类型的元素。数组类型的组件类型必须是可重复的注解类型。Schedules包含注解类型的声明如下:

public @interface Schedules {
Schedule[] value();
}

1.检索注解

Reflection API中有几种可用于检索注解的方法。返回单个注解的方法(例如 AnnotatedElement.getAnnotation(Class ))的行为未更改,因为如果存在所请求类型的一个注解,它们仅返回单个注解。如果存在多个所请求类型的注解,则可以通过首先获取其容器注解来获取它们。通过这种方式,遗留代码继续工作。Java SE 8中引入了其他方法,它们扫描容器注解以一次返回多个注解,例如 AnnotatedElement.getAnnotationsByType(Class )。请参阅 AnnotatedElement 有关所有可用方法的信息的类规范。

2.设计注意事项

设计注解类型时,必须考虑该类型注解的基数。现在可以使用注解零次,一次,或者,如果注解的类型被标记为@Repeatable多次,则不止一次。还可以通过使用@Target元注解来限制可以使用注解类型的位置。例如,可以创建只能在方法和字段上使用的可重复注解类型。仔细设计注解类型非常重要,以确保使用注解的程序员发现它尽可能灵活和强大。

二.类型注解和可插入类型系统

在Java SE 8发行版之前,注解只能应用于声明。从Java SE 8发行版开始,注解也可以应用于任何类型的使用。这意味着可以在任何使用类型的地方使用注解。使用where类型的一些示例是类实例创建表达式(new),强制转换,implements子句和throws子句。

  • 创建实例表达式时
new @Interned MyObject();
  • 类型转换:
myString = (@NonNull String) str;
  • 实现时:
class UnmodifiableList<T> implements
@Readonly List<@Readonly T> { ... }
  • 声明抛出异常:
void monitorTemperature() throws
@Critical TemperatureException { ... }

在元注解@Target中增加了作用类型:

/**
* Type parameter declaration
*
* @since 1.8
*/
TYPE_PARAMETER, /**
* Use of a type
*
* @since 1.8
*/
TYPE_USE

创建类型注解是为了支持改进的Java程序分析,以确保更强的类型检查。Java SE 8版本不提供类型检查框架,但它允许编写(或下载)类型检查框架,该框架实现为与Java编译器结合使用的一个或多个可插入模块。

例如,希望确保程序中的特定变量永远不会分配给null; 你想避免触发一个NullPointerException。可以编写自定义插件来检查此问题。然后,将修改代码以注解该特定变量,表明它从未分配给null。变量声明可能如下所示:

@NonNull String str;

当编译代码(包括NonNull命令行中的模块)时,编译器会在检测到潜在问题时输出警告,允许修改代码以避免错误。在更正代码以删除所有警告后,程序运行时不会发生此特定错误。

可以使用多个类型检查模块,其中每个模块检查不同类型的错误。通过这种方式,可以在Java类型系统的基础上构建,在希望的时间和地点添加特定的检查。

通过明智地使用类型注解和可插入类型检查器的存在,可以编写更强大且更不容易出错的代码。

在许多情况下,不必编写自己的类型检查模块。有第三方为你完成了这项工作。例如,可能希望利用华盛顿大学创建的Checker Framework。该框架包括一个NonNull模块,一个正则表达式模块和一个互斥锁模块。有关更多信息,请参阅 Checker Framework。

参考

Repeating Annotations

Type Annotations and Pluggable Type Systems

Java 8——重复注解和注解的作用范围的扩大化的更多相关文章

  1. JAVA中如何定义自定义注解

    了解注解 注解是Java1.5,JDK5.0引用的技术,与类,接口,枚举处于同一层次 .它可以声明在包.类.字段.方法.局部变量.方法参数等的前面,用来对这些元素进行说明,注释 . 在Java中,自带 ...

  2. Java注解(1)-注解基础

    注解(Annotation)是在JAVA5中开始引入的,它为在代码中添加信息提供了一种新的方式.注解在一定程度上把元数据与源代码文件结合在一起,正如许多成熟的框架(Spring)所做的那样.那么,注解 ...

  3. Effective Java 第三版——39. 注解优于命名模式

    Tips <Effective Java, Third Edition>一书英文版已经出版,这本书的第二版想必很多人都读过,号称Java四大名著之一,不过第二版2009年出版,到现在已经将 ...

  4. 【Java编程思想笔记】注解--元注解

    参考文章:(小白的小小白的白 )https://blog.csdn.net/weixin_42315600/article/details/80630669 https://www.cnblogs.c ...

  5. Java编程思想学习笔记——注解

    前言 在Android开发的过程中,我们为了减少重复代码的编写,会使用类似ButterKnife,AndroidAnnotations 这类依赖注解库.代码示例如下: //不使用 Button btn ...

  6. Java反射API研究(1)——注解Annotation

    注解在表面上的意思,只是标记一下这一部分,最好的注解就是代码自身.而在java上,由于注解的特殊性,可以通过反射API获取,这种特性使得注解被广泛应用于各大框架,用于配置内容,代替xml文件配置. 要 ...

  7. 夯实Java基础(十七)——注解(Annotation)

    1.注解概述 从JDK5.0开始,Java增加对元数据(MetaData)的支持,也就是注解(Annotation).其实我们早就已经接触过注解了,例如我们经常在Java代码中可以看到 “@Overr ...

  8. java8-13-默认方法 静态方法 重复注解 类型注解

    java8增加默认方法 静态方法   重复注解 类型注解   1.默认方法 default修饰   为什么要有这个特性? 当修改接口时候,需要修改全部实现该接口的类.为了解决这个问题,所以引进默认方法 ...

  9. 大数据JavaWeb之java基础巩固----Junit&反射&注解

    最近打算从0开始学学大数据,目前的主业是Android开发,但是当年毕业之后其实是搞J2EE的,所以打算没事又来拓展一下后台的技能,扩宽一下自己的知识体系对于自己的未来也能够多一些可能,另外大数据的一 ...

随机推荐

  1. Eclipse官方下载步骤

    今天整理Eclipse项目时,发现自己的IDE不能用了,不兼容自己的JDK,于是决定去官网下载一个适合的IDE,由于官网全部都是英文,所以不是太容易找到,于是就想着出一篇博客帮助以后的人更好的更快的下 ...

  2. Flink入门(三)——环境与部署

    flink是一款开源的大数据流式处理框架,他可以同时批处理和流处理,具有容错性.高吞吐.低延迟等优势,本文简述flink在windows和linux中安装步骤,和示例程序的运行,包括本地调试环境,集群 ...

  3. react-native修改xcode项目名

    目录 1. 选中旧工程名,改为新的工程名 2. 依次选择黄色文件夹,修改名字,千万不要在Xcode外修改!!! 3. 点击Find,点击Find and Replace in Project... 4 ...

  4. [TimLinux] JavaScript 事件

    1. 简介 JavaScript与HTML之间的交互式通过事件来实现的,事件是文档或浏览器窗口中发生的一些特定的交互瞬间,使用事件处理程序来预订事件,从而在事件发生时,能够执行特定的代码.事件使页面的 ...

  5. 【重温基础】instanceof运算符

    最近开始在整理ES6/ES7/ES8/ES9的知识点(已经上传到 我的博客 上),碰到一些知识点是自己已经忘记(用得少的知识点),于是也重新复习了一遍. 这篇文章要复习的 instanceof 是我在 ...

  6. 大数据学习笔记——Spark工作机制以及API详解

    Spark工作机制以及API详解 本篇文章将会承接上篇关于如何部署Spark分布式集群的博客,会先对RDD编程中常见的API进行一个整理,接着再结合源代码以及注释详细地解读spark的作业提交流程,调 ...

  7. Java Properties 加载

    static{ Properties prop = new Properties(); prop.load(Thread.currentThread().getContextClassLoader() ...

  8. 基于JavaScript google map集成流程

    google地图集成流程 一.获取Google Map API密钥 1.进入Google官网 => https://www.google.com.hk/ ,申请一个谷歌账号(如果没有)然后访问下 ...

  9. 面试百度、阿里、腾讯,这134道Java面试题你会多少?

    这里一共是134道Java面试题,看看你能对几道吧! 1. Java 语言有哪些特点 2. 面向对象和面向过程的区别 3. 关于 JVM JDK 和 JRE 最详细通俗的解答 4. Oracle JD ...

  10. zabbix 监控apache

    现在是客户端 1.安装zabbix的rpm源 1 rpm -ivh http://repo.zabbix.com/zabbix/4.4/rhel/7/x86_64/zabbix-release-4.4 ...