《Effective Java》解读第49条:检查参数的有效性

第49条:检查参数的有效性

几乎所有公有方法和构造器,都要对传入参数做合法性校验,非法参数应该尽早失败,而不是等到执行中途才崩溃。

这也是新手,在第一次接触真实项目时经常会犯得错误,毕竟当写个人项目时你可以随意一点,但是在企业复杂庞大的项目中,方法的参数校验是十分重要的,及时的抛出异常。

  1. 及时校验方法参数
    若传递了一个无效参数,在方法开头就对参数进行了校验,那么可以很快的发现异常,不要等到在执行过程中失败,最糟糕的情况是无效参数正常执行返回错误的结果。
  2. 对于共有方法必须进行校验,私有的可以不校验
    公有方法是对外契约,别人乱传参数你必须拦截;私有方法是自己内部调用,可控,可以省略校验。
  3. 校验失败统一抛出标准异常
    不要抛自定义乱七八糟异常,遵循 Java 约定,本书中指的底层入参合法性校验、编程错误。我们开发web项目出现的业务异常,使用统一的自定义异常即可。

当成也有例外,对于一些不实际的校验,是可以不校验的,比如在sort(list)前校验每个元素的可以排序的,这没有什么意义。

校验也不是越多越好,要在方法设计考虑通用性,尽量简洁,只添加必要的检查。

例如

参数校验

java 复制代码
public void setAge(int age) {
    // 先校验参数,再执行业务逻辑
    if (age < 0 || age > 150) {
        throw new IllegalArgumentException("年龄不合法:" + age);
    }
    // 业务逻辑
}

空指针校验

java 复制代码
public void print(String msg) {
    Objects.requireNonNull(msg, "msg不能为null");
}

这是书中推荐的,真实项目很少用。业务开发一般使用自定义的异常。

注意点

  1. 先赋值成员变量,再校验参数 ❌
    错误构造器先把非法参数赋值给字段,对象已经非法了。正确:先校验 → 再赋值
  2. 空字符串判断
    字符串要同时判 null 和空:if(str == null || str.isBlank())。
    一般使用
java 复制代码
StringUtils.isEmpty(str);

这里也衍生出其他问题,比如List不为空,但是list中没有元素的校验。

有一个小技巧,如果是字符串使用StringUtils.isEmpty(str)或StringUtils.hasText(str),否则使用ObjectUtils.isEmpty(str),内部对于各种容器等都进行的判断。

源码:

java 复制代码
public static boolean isEmpty(@Nullable Object obj) {
    if (obj == null) {
        return true;
    } else if (obj instanceof Optional) {
        Optional<?> optional = (Optional)obj;
        return optional.isEmpty();
    } else if (obj instanceof CharSequence) {
        CharSequence charSequence = (CharSequence)obj;
        return charSequence.isEmpty();
    } else if (obj.getClass().isArray()) {
        return Array.getLength(obj) == 0;
    } else if (obj instanceof Collection) {
        Collection<?> collection = (Collection)obj;
        return collection.isEmpty();
    } else if (obj instanceof Map) {
        Map<?, ?> map = (Map)obj;
        return map.isEmpty();
    } else {
        return false;
    }
}
  1. 校验逻辑写在工具方法里,公有方法不校验对
    外接口必须自己校验,不能依赖内部工具。
  2. 返回错误码,不抛异常违反本条设计哲学:非法参数是编程错误,不是业务异常,应该直接崩溃失败快速,不能吞错。
  3. 个人建议在调用外部接口获取数据时,对返回结果进行空校验,同时在使用Stream前对于数据进行空校验。

总结

更重要的是在日常养成好的习惯,在写方法时就考虑好参数的限制。不要当出现问题时,才明白参数校验的重要性。

相关推荐
kernelcraft1 分钟前
Boto3:Python 操作 AWS 的官方 SDK
开发语言·python·其他·aws
D3bugRealm13 分钟前
cryptography:Python 开发者的加密标准库
开发语言·python·其他
Rain50920 分钟前
2.1 Nest.js 项目初始化与模块化架构
开发语言·前端·javascript·后端·架构·数据分析·node.js
小熊美家熊猫系统39 分钟前
电子合同技术实现与合规实践
java·开发语言·分布式
云烟成雨TD39 分钟前
Agent Scope Java 2.x 系列【3】从零构建 ReActAgent
java·人工智能·agent
ytttr87342 分钟前
C# 定时数据库备份工具
开发语言·数据库·c#
一只叫煤球的猫1 小时前
ThreadForge 源码解读二:一个 Task 从 submit 到完成,内部到底发生了什么?
java·后端·面试
skywalk81631 小时前
言知项目后续方向建议
开发语言·学习·编程
阿狸猿1 小时前
论微服务架构及其应用
java·微服务·架构
拉勾科研工作室2 小时前
区块链工程毕业论文题目【249个】
开发语言·javascript