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

总结

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

相关推荐
zhangfeng113327 分钟前
openclaw skills 小龙虾技能 通讯仿真 matlab skill Simulink Agentic Toolkit,通过kimi找到,mcp通讯
开发语言·matlab·openclaw·通讯仿真
Javatutouhouduan7 小时前
2026Java面试的正确打开方式!
java·高并发·java面试·java面试题·后端开发·java编程·java八股文
chao1898447 小时前
基于 SPEA2 的多目标优化算法 MATLAB 实现
开发语言·算法·matlab
JAVA面经实录9177 小时前
Java初级最终完整版学习路线图
java·spring·eclipse·maven
赏金术士7 小时前
Kotlin 习题集 · 高级篇
android·开发语言·kotlin
Cat_Rocky8 小时前
k8s-持久化存储,粗浅学习
java·学习·kubernetes
楼兰公子8 小时前
buildroot 在编译rust时裁剪平台类型数量的方法
开发语言·后端·rust
知识领航员8 小时前
蘑兔AI音乐深度实测:功能拆解、实测表现与适用场景
java·c语言·c++·人工智能·python·算法·github
吴声子夜歌9 小时前
Go——并发编程
开发语言·后端·golang
释怀°Believe9 小时前
Spring解析
java·后端·spring