读书笔记-《ON JAVA 中文版》-摘要26[第二十三章 注解]
文章目录
- 第二十三章 注解
- 1. 基本语法
- 1.1 基本语法
- 1.2 定义注解
- 1.3 元注解
- 2. 编写注解处理器
- 2.1 编写注解处理器
- 2.2 注解元素
- 2.3 默认值限制
- 3. 使用javac处理注解
- 4. 基于注解的单元测试
- 5. 本章小结
第二十三章 注解
注解(也被称为元数据)为我们在代码中添加信息提供了一种形式化的方式,使我们可以在稍后的某个时刻更容易的使用这些数据。
通过使用注解,你可以将元数据保存在 Java 源代码中。并拥有如下有下优势:简单易读的代码,编译器类型检查,使用 annotation API 为自己的注解构造处理工具。
注解的语法十分简单,主要是在现有语法中添加 @ 符号。
1. 基本语法
1.1 基本语法
使用 @Test 对 testExecute() 进行注解。该注解本身不做任何事情,但是编译器要保证其类路径上有 @Test 注解的定义。
package annotations;import onjava.atunit.Test;public class Testable {public void execute() {System.out.println("Executing..");}@Testvoid testExecute() { execute(); }
}
1.2 定义注解
注解的定义看起来很像接口的定义。事实上,它们和其他 Java 接口一样,也会被编译成 class 文件。
package onjava.atunit;import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Test {
}
@Target 定义你的注解可以应用在哪里(例如是方法还是字段)。 @Retention 定义了注解在哪里可用,在源代码中(SOURCE),class文件(CLASS)中或者是在运行时(RUNTIME)。
不包含任何元素的注解称为标记注解(marker annotation),例如上例中的 @Test 就是标记注解。
下面是一个简单的注解,我们可以用它来追踪项目中的用例。
package annotations;import java.util.List;public class PasswordUtils {// 注解的元素在使用时表现为 名-值 对的形式,并且需要放置在 @UseCase 声明之后的括号内。@UseCase(id = 47, description ="Passwords must contain at least one numeric")public boolean validatePassword(String passwd) {return (passwd.matches("\\w*\\d\\w*"));}@UseCase(id = 48)public String encryptPassword(String passwd) {return new StringBuilder(passwd).reverse().toString();}@UseCase(id = 49, description ="New passwords can't equal previously used ones")public boolean checkForNewPassword(List<String> prevPasswords, String passwd) {return !prevPasswords.contains(passwd);}
}
1.3 元注解
Java 语言中目前有 5 种标准注解:
-
@Override:表示当前的方法定义将覆盖基类的方法。如果你不小心拼写错误,或者方法签名被错误拼写的时候,编译器就会发出错误提示。
-
@Deprecated:如果使用该注解的元素被调用,编译器就会发出警告信息。
-
@SuppressWarnings:关闭不当的编译器警告信息。
-
@SafeVarargs:在 Java 7 中加入用于禁止对具有泛型varargs参数的方法或构造函数的调用方发出警告。
-
@FunctionalInterface:Java 8 中加入用于表示类型声明为函数式接口
以及 5 种元注解。元注解用于注解其他的注解
注解 | 解释 |
---|---|
@Target | 表示注解可以用于哪些地方。可能的 ElementType 参数包括: CONSTRUCTOR:构造器的声明 FIELD:字段声明(包括 enum 实例) LOCAL_VARIABLE:局部变量声明 METHOD:方法声明 PACKAGE:包声明 PARAMETER:参数声明 TYPE:类、接口(包括注解类型)或者 enum 声明 |
@Retention | 表示注解信息保存的时长。可选的 RetentionPolicy 参数包括: SOURCE:注解将被编译器丢弃 SOURCE:注解将被编译器丢弃 CLASS:注解在 class 文件中可用,但是会被 VM 丢弃。 RUNTIME:VM 将在运行期也保留注解,因此可以通过反射机制读取注解的信 息。 |
@Documented | 将此注解保存在 Javadoc 中 |
@Inherited | 允许子类继承父类的注解 |
@Repeatable | 允许一个注解可以被使用一次或者多次 |
2. 编写注解处理器
2.1 编写注解处理器
如果没有用于读取注解的工具,那么注解不会比注释更有用。使用注解中一个很重要的部分就是,创建与使用注解处理器。
下面是一个非常简单的注解处理器,我们用它来读取被注解的 PasswordUtils 类,并且使用反射机制来寻找 @UseCase 标记。
package annotations;import java.lang.reflect.Method;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.IntStream;public class UseCaseTracker {public static voidtrackUseCases(List<Integer> useCases, Class<?> cl) {for (Method m : cl.getDeclaredMethods()) {UseCase uc = m.getAnnotation(UseCase.class);if (uc != null) {System.out.println("Found Use Case " +uc.id() + "\n " + uc.description());useCases.remove(Integer.valueOf(uc.id()));}}useCases.forEach(i ->System.out.println("Missing use case " + i));}public static void main(String[] args) {List<Integer> useCases = IntStream.range(47, 51).boxed().collect(Collectors.toList());trackUseCases(useCases, PasswordUtils.class);}
}
输出:
Found Use Case 47Passwords must contain at least one numeric
Found Use Case 49New passwords can't equal previously used ones
Found Use Case 48no description
Missing use case 50
2.2 注解元素
在 UseCase.java 中定义的 @UseCase 的标签包含 int 元素 id 和 String 元素 description。注解元素可用的类型如下所示:
-
所有基本类型(int、float、boolean等)
-
String
-
Class
-
enum
-
Annotation
-
以上类型的数组
2.3 默认值限制
编译器对于元素的默认值有些过于挑剔。首先,元素不能有不确定的值。也就是说,元素要么有默认值,要么就在使用注解时提供元素的值。
这里有另外一个限制:任何非基本类型的元素, 无论是在源代码声明时还是在注解接口中定义默认值时,都不能使用 null 作为其值。这个限制使得处理器很难表现一个元素的存在或者缺失的状态,因为在每个注解的声明中,所有的元素都存在,并且具有相应的值。为了绕开这个约束,可以自定义一些特殊的值,比如空字符串或者负数用于表达某个元素不存在。
package annotations;import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface SimulatingNull {int id() default -1;String description() default "";
}
注解不支持继承
3. 使用javac处理注解
通过 javac,你可以通过创建编译时(compile-time)注解处理器在 Java 源文件上使用注解,而不是编译之后的 class 文件。
每一个你编写的注解都需要处理器,但是 javac 可以非常容易的将多个注解处理器合并在一起。你可以指定多个需要处理的类,并且你可以添加监听器用于监听注解处理完成后接到通知。
4. 基于注解的单元测试
单元测试是对类中每个方法提供一个或者多个测试的一种事件,其目的是为了有规律的测试一个类中每个部分是否具备正确的行为。在 Java 中,最著名的单元测试工具就是 JUnit。JUnit 4 版本已经包含了注解。
5. 本章小结
注解是 Java 引入的一项非常受欢迎的补充,它提供了一种结构化,并且具有类型检查能力的新途径,从而使得你能够为代码中加入元数据,而且不会导致代码杂乱并难以阅读。
而 Javadoc 中的 @deprecated 被 @Deprecated 注解所替代的事实也说明,与注释性文字相比,注解绝对更适用于描述类相关的信息。
Java 提供了很少的内置注解。这意味着如果你在别处找不到可用的类库,那么就只能自己创建新的注解以及相应的处理器。通过将注解处理器链接到 javac,你可以一步完成编译新生成的文件,简化了构造过程。
API 的提供方和框架将会将注解作为他们工具的一部分。通过 @Unit 系统,我们可以想象,注解会极大的改变我们的 Java 编程体验。
(图网,侵删)
相关文章:

读书笔记-《ON JAVA 中文版》-摘要26[第二十三章 注解]
文章目录 第二十三章 注解1. 基本语法1.1 基本语法1.2 定义注解1.3 元注解 2. 编写注解处理器2.1 编写注解处理器2.2 注解元素2.3 默认值限制 3. 使用javac处理注解4. 基于注解的单元测试5. 本章小结 第二十三章 注解 注解(也被称为元数据)为我们在代码…...

IDEA报Error:java:无效的源发行版13解决方式
出现问题原因:原本项目是spingboot2.0版本开发的,IDEA启动正常,后期新项目使用spingboot3.0,通过原来的IDEA版本及JDK1.8启动报上述错误,以下为版本文件 解决方式: 项目背景:项目已经上线&…...

基于SpringBoot的健身房管理系统
目录 前言 一、技术栈 二、系统功能介绍 会员信息管理 员工信息管理 会员卡类型管理 健身项目管理 会员卡管理 三、核心代码 1、登录模块 2、文件上传模块 3、代码封装 前言 随着信息技术在管理上越来越深入而广泛的应用,管理信息系统的实施在技术上已逐步…...

竞赛选题 深度学习 植物识别算法系统
文章目录 0 前言2 相关技术2.1 VGG-Net模型2.2 VGG-Net在植物识别的优势(1) 卷积核,池化核大小固定(2) 特征提取更全面(3) 网络训练误差收敛速度较快 3 VGG-Net的搭建3.1 Tornado简介(1) 优势(2) 关键代码 4 Inception V3 神经网络4.1 网络结构 5 开始训练5.1 数据集…...

希尔贝壳受邀参加《人工智能开发平台通用能力要求 第4部分:大模型技术要求》标准第一次研讨会
随着大模型技术与经验的不断累积,该方向也逐渐从聚焦技术突破,到关注开发、部署、应用的全流程工程化落地。为完善人工智能平台标准体系建设,满足产业多样化需求,2023年9月7日,中国信通院云大所在线上召开《人工智能开…...

虹科方案 | AR助力仓储物流突破困境:规模化运营与成本节约
文章来源:虹科数字化AR 点击阅读原文:https://mp.weixin.qq.com/s/xis_I5orLb6RjgSokEhEOA 虹科方案一览 HongKe DigitalizationAR 当今的客户体验要求企业在人员、流程和产品之间实现全面的连接。为了提升整个组织的效率并提高盈利能力,物流…...

spring容器ioc和di
spring ioc 容器的创建 BeanFactory 接口提供了一种高级配置机制,能够管理任何类型的对象,它是SpringIoC容器标准化超接口! ApplicationContext 是 BeanFactory 的子接口。它扩展了以下功能: 更容易与 Spring 的 AOP 功能集成消…...
Maven 仓库地址
一、Maven 中央仓库地址 http://www.sonatype.org/nexus/http://mvnrepository.com/ (本人推荐仓库)http://repo1.maven.org/maven2 二、Maven 中央仓库地址大全 1、阿里中央仓库(首选推荐) <repository> <id>al…...

【2023研电赛】安谋科技企业命题特别奖:面向独居老人的智能居家监护系统
本文为2023年第十八届中国研究生电子设计竞赛安谋科技企业命题特别奖分享,参加极术社区的【有奖活动】分享2023研电赛作品扩大影响力,更有丰富电子礼品等你来领!,分享2023研电赛作品扩大影响力,更有丰富电子礼品等你来…...

[Machine learning][Part4] 多维矩阵下的梯度下降线性预测模型的实现
目录 模型初始化信息: 模型实现: 多变量损失函数: 多变量梯度下降实现: 多变量梯度实现: 多变量梯度下降实现: 之前部分实现的梯度下降线性预测模型中的training example只有一个特征属性:…...
LCR 078. 合并 K 个升序链表
LCR 078. 合并 K 个升序链表 题目链接:LCR 078. 合并 K 个升序链表 代码如下: class Solution { public:ListNode* mergeKLists(vector<ListNode*>& lists) {ListNode *lsnullptr;for(int i0;i<lists.size();i){lsmergeList(ls,lists[i])…...

JVM面试题:(三)GC和垃圾回收算法
GC: 垃圾回收算法: GC最基础的算法有三种: 标记 -清除算法、复制算法、标记-压缩算法,我们常用的垃圾回收器一般 都采用分代收集算法。 标记 -清除算法,“标记-清除”(Mark-Sweep)算法,如它的…...
hive建表指定列分隔符为多字符分隔符实战(默认只支持单字符)
1、背景: 后端日志采集完成,清洗入hive表的过程中,发现字段之间的单一字符的分割符号已经不能满足列分割需求,因为字段值本身可能包含分隔符。所以列分隔符使用多个字符列分隔符迫在眉睫。 hive在建表时,通常使用ROW …...
android.app.RemoteServiceException: can‘t deliver broadcast
日常报错记录 android.app.RemoteServiceException: cant deliver broadcast W BroadcastQueue: Cant deliver broadcast to com.broadcast.test(pid 1769). Crashing it.E AndroidRuntime: FATAL EXCEPTION: main E AndroidRuntime: Process: com.broadcast.test, PID: 1769…...

信创办公–基于WPS的EXCEL最佳实践系列 (单元格与行列)
信创办公–基于WPS的EXCEL最佳实践系列 (单元格与行列) 目录 应用背景操作步骤1、插入和删除行和列2、合并单元格3、调整行高与列宽4、隐藏行与列5、修改单元格对齐和缩进6、更改字体7、使用格式刷8、设置单元格内的文本自动换行9、应用单元格样式10、插…...

VsCode同时编译多个C文件
VsCode默认只能编译单个C文件,想要编译多个文件,需要额外进行配置 第一种方法 ——> 通过手动指定要编译的文件 g -g .\C文件1 .\C文件2 -o 编译后exe名称 例如我将demo.c和extern.c同时编译得到haha.exe g -g .\demo.c .\extern.c -o haha 第二种…...

Android绑定式服务
Github:https://github.com/MADMAX110/Odometer 启动式服务对于后台操作很合适,不过需要一个更有交互性的服务。 接下来构建这样一个应用: 1、创建一个绑定式服务的基本版本,名为OdometerService 我们要为它增加一个方法getDistance()&#x…...

系统韧性研究(1)| 何谓「系统韧性」?
过去十年,系统韧性作为一个关键问题被广泛讨论,在数据中心和云计算方面尤甚,同时它对赛博物理系统也至关重要,尽管该术语在该领域不太常用。大伙都希望自己的系统具有韧性,但这到底意味着什么?韧性与其他质…...

使用Perl脚本编写爬虫程序的一些技术问题解答
网络爬虫是一种强大的工具,用于从互联网上收集和提取数据。Perl 作为一种功能强大的脚本语言,提供了丰富的工具和库,使得编写的爬虫程序变得简单而灵活。在使用的过程中大家会遇到一些问题,本文将通过问答方式,解答一些…...

SAP内部转移价格(利润中心转移价格)的条件
SAP内部转移价格(利润中心转移价格) SAP内部转移价格(利润中心转移价格) SAP内部转移价格(利润中心转移价格)这个听了很多人说过,但是利润中心转移定价需要具备什么条件。没有找到具体的文档。…...
DeepSeek 赋能智慧能源:微电网优化调度的智能革新路径
目录 一、智慧能源微电网优化调度概述1.1 智慧能源微电网概念1.2 优化调度的重要性1.3 目前面临的挑战 二、DeepSeek 技术探秘2.1 DeepSeek 技术原理2.2 DeepSeek 独特优势2.3 DeepSeek 在 AI 领域地位 三、DeepSeek 在微电网优化调度中的应用剖析3.1 数据处理与分析3.2 预测与…...
【解密LSTM、GRU如何解决传统RNN梯度消失问题】
解密LSTM与GRU:如何让RNN变得更聪明? 在深度学习的世界里,循环神经网络(RNN)以其卓越的序列数据处理能力广泛应用于自然语言处理、时间序列预测等领域。然而,传统RNN存在的一个严重问题——梯度消失&#…...

ServerTrust 并非唯一
NSURLAuthenticationMethodServerTrust 只是 authenticationMethod 的冰山一角 要理解 NSURLAuthenticationMethodServerTrust, 首先要明白它只是 authenticationMethod 的选项之一, 并非唯一 1 先厘清概念 点说明authenticationMethodURLAuthenticationChallenge.protectionS…...

新能源汽车智慧充电桩管理方案:新能源充电桩散热问题及消防安全监管方案
随着新能源汽车的快速普及,充电桩作为核心配套设施,其安全性与可靠性备受关注。然而,在高温、高负荷运行环境下,充电桩的散热问题与消防安全隐患日益凸显,成为制约行业发展的关键瓶颈。 如何通过智慧化管理手段优化散…...

第 86 场周赛:矩阵中的幻方、钥匙和房间、将数组拆分成斐波那契序列、猜猜这个单词
Q1、[中等] 矩阵中的幻方 1、题目描述 3 x 3 的幻方是一个填充有 从 1 到 9 的不同数字的 3 x 3 矩阵,其中每行,每列以及两条对角线上的各数之和都相等。 给定一个由整数组成的row x col 的 grid,其中有多少个 3 3 的 “幻方” 子矩阵&am…...
docker 部署发现spring.profiles.active 问题
报错: org.springframework.boot.context.config.InvalidConfigDataPropertyException: Property spring.profiles.active imported from location class path resource [application-test.yml] is invalid in a profile specific resource [origin: class path re…...
【Java学习笔记】BigInteger 和 BigDecimal 类
BigInteger 和 BigDecimal 类 二者共有的常见方法 方法功能add加subtract减multiply乘divide除 注意点:传参类型必须是类对象 一、BigInteger 1. 作用:适合保存比较大的整型数 2. 使用说明 创建BigInteger对象 传入字符串 3. 代码示例 import j…...

20个超级好用的 CSS 动画库
分享 20 个最佳 CSS 动画库。 它们中的大多数将生成纯 CSS 代码,而不需要任何外部库。 1.Animate.css 一个开箱即用型的跨浏览器动画库,可供你在项目中使用。 2.Magic Animations CSS3 一组简单的动画,可以包含在你的网页或应用项目中。 3.An…...
C#中的CLR属性、依赖属性与附加属性
CLR属性的主要特征 封装性: 隐藏字段的实现细节 提供对字段的受控访问 访问控制: 可单独设置get/set访问器的可见性 可创建只读或只写属性 计算属性: 可以在getter中执行计算逻辑 不需要直接对应一个字段 验证逻辑: 可以…...

GitFlow 工作模式(详解)
今天再学项目的过程中遇到使用gitflow模式管理代码,因此进行学习并且发布关于gitflow的一些思考 Git与GitFlow模式 我们在写代码的时候通常会进行网上保存,无论是github还是gittee,都是一种基于git去保存代码的形式,这样保存代码…...