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

总结

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

相关推荐
小羊没烦恼!2 天前
微服务化的基石——持续集成
java·大数据·word·powerpoint·.net
俊昭喜喜里2 天前
java中的继承和多态的区别
java
小羊没烦恼!2 天前
初探性能优化——2个月到4小时的性能提升
java·开发语言·windows·算法·c#
譕痕2 天前
JSONObject与JSONArray封装数据格式区别
java·json
胡写代码2 天前
别再前后端各写一套表单校验了
java·后端
小鱼能吃糖2 天前
缺陷修复总览 · mall电商项目:5类缺陷,1个病根,4个业务域
java·电商
此时不提桶,更待何时2 天前
01-06-A-JVM排查实战详解
java·jvm
伞伞悦读2 天前
【第38期】Python 模块与包详解:import、from、模块搜索路径、包结构和 __init__
开发语言·python
vipxieliang2 天前
ValidX 在 DDD 领域驱动设计中的实践
java·spring boot
C语言小火车2 天前
C/C++ 为什么需要编译器?
开发语言·c++