《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前对于数据进行空校验。

总结

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

相关推荐
诚心呈意共享外卖配送系统1 分钟前
多平台订单聚合系统的技术架构:接 API 只是开始
java·开发语言·架构·系统架构·创业创新
Java爱好狂.6 分钟前
Java小白如何三天速通redis?
java·数据库·redis·架构师·分布式锁·java面试·java程序员
大风起兮云飞扬丶7 分钟前
Java——多线程
java
天若有情67317 分钟前
从零搭建校园二手交易系统:Vue2 + SpringBoot 4.x 全栈实战
java·spring boot·后端
学逆向的17 分钟前
C 浮点数e(科学计数法)
c语言·开发语言·网络安全
lexiangqicheng26 分钟前
1,自定义表单通俗理解-PC设计APP渲染
java·前端·javascript
quantdash_cc28 分钟前
如何给自己的量化策略增加独立数据层?从数据获取到策略解耦的 Python 实践
开发语言·python·数据分析·量化交易·股票数据·quantdash
NeoGressAI外贸数字化29 分钟前
外贸独立站3类页面合格度,怎么用脚本一次跑完
开发语言·python
南极企鹅35 分钟前
生产环境gc文件分析
java·jvm·算法
Wang's Blog36 分钟前
Java 项目实战: 交友项目 - 前后端分离的工程实践
java·spring cloud·架构