Java架构师教你编码规范-如何校验参数?

简介: Java架构师教你编码规范-如何校验参数?

1 参数校验的意义

大多数方法对传递给它们的参数值有限制。例如,索引值必须非负,对象引用必须非空。

  • 应该清楚地在文档中记录所有这些限制,并在方法主体的开头使用检查来实施它们。
  • 应该在错误发生后尽快找到它们,这是一般原则。如果不这样做,就不太可能检测到错误,而且即使检测到错误,确定错误的来源也很难。

若一个无效参数被传递给一个方法

  • 若该方法在执行前检查参数,这过程将迅速失败,并引发异常
  • 若方法未检查参数,可能会在处理过程中出现:

    • 莫名其妙的异常而失败
    • 正常返回,但会悄悄计算错误结果
    • 正常返回,但会使某对象处于隐患状态,可能在未来某不确定时间在某不相关代码点报错。

总之,若无验证参数,可能会违反失败原子性。

对public、protected方法,要在方法说明使用 Javadoc 的 @throws 标签说明如果违反参数值限制时会抛出的异常。通常为 IllegalArgumentExceptionIndexOutOfBoundsExceptionNullPointerException。一旦在文档中记录了方法参数上的限制,并且记录违反这些限制将引发的异常,强加这些限制就很简单了。

  • 看案例:

文档注释并没说「若 m 为空,mod 将抛NPE」,尽管方法确实这么做了,作为调用 m.signum() 的副产物。该异常记录在外围 BigInterger 类级别的文档注释。类级别注释适用于类的所有public方法中的所有参数。这可以避免在每个方法上分别记录每个 NullPointerException 而造成混乱。
它可与 @Nullable 或类似注解结合使用,以指示某特定参数可能为 null,但这种做法并不标准,而且使用了多个注解。

2 最佳实践

Java 7 提供 Objects.requireNonNull 不再需手动执行空检查。

如果愿意,还可自定义异常详情。该方法返回其输入,所以使用一个值的同时可执行判空:

// 内置 Java 的判空功能
this.strategy = Objects.requireNonNull(strategy, "strategy");

也可以忽略返回值并使用 Objects.requireNonNull 作为一个独立判空方法。

3 边界检查

在 Java 9 中,边界检查功能被添加到 java.util.Objects。该功能由三个方法组成:

  • checkFromIndexSize
  • checkFromToIndex
  • checkIndex

该套工具不如判空方法灵活。它不允许自定义异常详细信息,仅适用于 List 和数组索引。它不处理封闭范围(包含两个端点)。

4 断言

对于未暴露的方法,作为包作者,你应该控制方法在何时能被调用,因此你可以并且也应该确保只传入有效参数值。因此,非public方法可使用断言检查入参:

从本质上说,这些断言是在声称被断言的条件为 true,而不管客户端如何调用。与普通校验不同的是:

  • 若断言失败,会抛 AssertionError
  • 若断言没有作用,本质上不存在成本,除非通过将 -ea( 或 -enableassertion)标识传递给 java 命令来启用它们

尤其应检查那些尚未由方法调用,而是存起供日后使用的参数的有效性。例如静态工厂方法,它接受 int 数组并返回数组的 List 视图。若客户端传入 null,将抛 NullPointerException,因为该方法具有显式检查(调用 Objects.requireNonNull)。如果省略检查,该将返回对新创建的 List 实例的引用,该实例将在客户端试图使用它时抛出 NullPointerException。到那时,List 实例的起源很难确定,使调试变得复杂。
构造器就是一种特殊情况。务必检查构造器入参有效性,避免构造生成实例对象时,违背对象的不变性。

在执行方法前,应显式检查参数,也有例外 - 有效性检查成本较高或不切实际,或检查在计算过程中隐式执行了。
例如,一个为对象 List 排序的方法,比如 Collections.sort(List)。List 中的所有对象必须相互比较。在对 List 排序的过程中,List 中的每个对象都会与列表中的其他对象进行比较。如果对象不能相互比较,将抛出 ClassCastException,这正是 sort 方法应该做的。因此,没有必要预先检查列表中的元素是否具有可比性。但不加区别地依赖隐式有效性检查可能导致失败原子性的丢失。

有时,计算任务会隐式地执行所需的有效性检查,但如果检查失败,则抛出错误的异常。即计算任务由于无效参数值所抛异常,与文档中记录的方法要抛出的异常不匹配。此时应该使用异常转换将计算任务抛出的异常转换为正确的异常。

5 总结

请勿从本规范推得:对参数的任意限制都是好事。相反的,应该把方法设计得既通用又实用。对参数施加的限制越少越好,假设该方法可对它所接受的所有参数值进行合理的处理。然而,一些限制常常是实现抽象的内在限制。

每次编写方法或构造器时,都应考虑参数存在哪些限制。你应该在文档中记录这些限制,并在方法主体的开头显式检查。养成这样的习惯!这一少量工作将在有效性检查出现第一次失败时连本带利地偿还给你!

目录
相关文章
|
消息中间件 Java Kafka
Java 事件驱动架构设计实战与 Kafka 生态系统组件实操全流程指南
本指南详解Java事件驱动架构与Kafka生态实操,涵盖环境搭建、事件模型定义、生产者与消费者实现、事件测试及高级特性,助你快速构建高可扩展分布式系统。
556 7
|
负载均衡 算法 关系型数据库
大数据大厂之MySQL数据库课程设计:揭秘MySQL集群架构负载均衡核心算法:从理论到Java代码实战,让你的数据库性能飙升!
本文聚焦 MySQL 集群架构中的负载均衡算法,阐述其重要性。详细介绍轮询、加权轮询、最少连接、加权最少连接、随机、源地址哈希等常用算法,分析各自优缺点及适用场景。并提供 Java 语言代码实现示例,助力直观理解。文章结构清晰,语言通俗易懂,对理解和应用负载均衡算法具有实用价值和参考价值。
大数据大厂之MySQL数据库课程设计:揭秘MySQL集群架构负载均衡核心算法:从理论到Java代码实战,让你的数据库性能飙升!
|
消息中间件 Java 数据库
Java 基于 DDD 分层架构实战从基础到精通最新实操全流程指南
本文详解基于Java的领域驱动设计(DDD)分层架构实战,结合Spring Boot 3.x、Spring Data JPA 3.x等最新技术栈,通过电商订单系统案例展示如何构建清晰、可维护的微服务架构。内容涵盖项目结构设计、各层实现细节及关键技术点,助力开发者掌握DDD在复杂业务系统中的应用。
2102 0
|
机器学习/深度学习 人工智能 文件存储
Llama Nemotron:英伟达开源基于Llama架构优化的推理模型,253B参数持平DeepSeek R1!
NVIDIA推出的Llama Nemotron系列推理模型,基于Llama架构优化,包含Nano/Super/Ultra三款,在数学推理、编程和工具调用等任务中展现卓越性能。
624 5
Llama Nemotron:英伟达开源基于Llama架构优化的推理模型,253B参数持平DeepSeek R1!
|
人工智能 安全 Java
智慧工地源码,Java语言开发,微服务架构,支持分布式和集群部署,多端覆盖
智慧工地是“互联网+建筑工地”的创新模式,基于物联网、移动互联网、BIM、大数据、人工智能等技术,实现对施工现场人员、设备、材料、安全等环节的智能化管理。其解决方案涵盖数据大屏、移动APP和PC管理端,采用高性能Java微服务架构,支持分布式与集群部署,结合Redis、消息队列等技术确保系统稳定高效。通过大数据驱动决策、物联网实时监测预警及AI智能视频监控,消除数据孤岛,提升项目可控性与安全性。智慧工地提供专家级远程管理服务,助力施工质量和安全管理升级,同时依托可扩展平台、多端应用和丰富设备接口,满足多样化需求,推动建筑行业数字化转型。
515 5
|
11月前
|
负载均衡 Java API
grpc-java 架构学习指南
本指南系统解析 grpc-java 架构,涵盖分层设计、核心流程与源码结构,结合实战路径与调试技巧,助你从入门到精通,掌握高性能 RPC 开发精髓。
975 8
|
Java Linux 定位技术
Minecraft配置文件参数说明(JAVA服务器篇)
Minecraft JAVA版服务器启动后会生成server.properties配置文件,位于minecraft_server/根目录下。该文件包含多项关键设置,如游戏模式(gamemode)、最大玩家数(max-players)、难度(difficulty)等。此文档详细说明了各配置项的功能与默认值,帮助用户高效管理服务器环境。
5049 62
Java程序员必学:JVM架构完全解读
Java 虚拟机(JVM)是 Java 编程的核心,深入理解其架构对开发者意义重大。本文详细解读 JVM 架构,涵盖类加载器子系统、运行时数据区等核心组件,剖析类加载机制,包括加载阶段、双亲委派模型等内容。阐述内存管理原理,介绍垃圾回收算法与常见回收器,并结合案例讲解调优策略。还分享 JVM 性能瓶颈识别与调优方法,分析 Java 语言特性对性能的影响,给出数据结构选择、I/O 操作及并发同步处理的优化技巧,同时探讨 JVM 安全模型与错误处理机制,助力开发者提升编程能力与程序性能。
Java程序员必学:JVM架构完全解读
|
算法 架构师 Java
Java 开发岗及 java 架构师百度校招历年经典面试题汇总
以下是百度校招Java岗位面试题精选摘要(150字): Java开发岗重点关注集合类、并发和系统设计。HashMap线程安全可通过Collections.synchronizedMap()或ConcurrentHashMap实现,后者采用分段锁提升并发性能。负载均衡算法包括轮询、加权轮询和最少连接数,一致性哈希可均匀分布请求。Redis持久化有RDB(快照恢复快)和AOF(日志更安全)两种方式。架构师岗涉及JMM内存模型、happens-before原则和无锁数据结构(基于CAS)。
440 5
|
缓存 Java 数据库
Java 项目分层架构实操指南及长尾关键词优化方案
本指南详解基于Spring Boot与Spring Cloud的Java微服务分层架构,以用户管理系统为例,涵盖技术选型、核心代码实现、服务治理及部署实践,助力掌握现代化Java企业级开发方案。
564 2