《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 小时前
C语言制作消消乐游戏(2)
c语言·开发语言·游戏
布谷歌2 小时前
常见的OOM错误 ( OutOfMemoryError全类型详解)
java·开发语言
WangJunXiang62 小时前
GFS分布式文件系统
开发语言·php
民乐团扒谱机2 小时前
【微实验】基于matlab的音频提取与信号滤波处理
开发语言·matlab·音视频
eLIN TECE2 小时前
springboot和springframework版本依赖关系
java·spring boot·后端
SomeB1oody2 小时前
【Python深度学习】3.4. 循环神经网络(RNN)实战:预测股价
开发语言·人工智能·python·rnn·深度学习·机器学习
良木生香2 小时前
【C++初阶】:STL——String从入门到应用完全指南(1)
c语言·开发语言·数据结构·c++·算法
老神在在0012 小时前
Spring Bean 的六种作用域详解
java·后端·spring
仙草不加料2 小时前
互联网大厂Java面试故事实录:三轮场景化技术提问与详细答案解析
java·spring boot·微服务·面试·aigc·电商·内容社区