likes
comments
collection
share

省略if表达式中else的问题

作者站长头像
站长
· 阅读数 4

最近看到自己以前写的代码,很多的if表达式用作防御,没有写else,看的时候产生一些疑惑,还有一些想法,由本文记录这些想法。

问题场景分析

我想大部分开发者应该都写过类似下面的代码:

void fun1(Object obj){
    if(obj != null){
        handleObj(obj);
        //...
    }
}

这里对参数进行检查,只有在参数合法的时候才执行对应操作。而参数不合法的时候则忽略,在代码中的体现为省略的else。这个代码在大多数情况是没有问题的,但当我一段时间后再去看这段代码的时候,产生了一些疑惑:这个else的情况是不需要处理的、可以忽略的情况?还是忘记写、疏忽了的情况?其实我不知道。甚至还有可能是写这段代码的时候,是可以忽略的情况,但随着功能演变,变成了必须要处理的情况,但是却没有处理,这就是一种比较糟糕的情况了,但这也是项目中很容易出现的情况。

优化和解决方案

下面分享几种优化和解决方案。

方案一、利用注释将else显式化

这种方法是不管什么情况都写else,但是在else的主体内,用注释说明情况,例如:

void fun1(Object obj) {
    if (obj != null) {
        handleObj(obj);
    } else {
        // obj为null的情况可忽略
    }
}

void fun1(Object obj) {
    if (obj != null) {
        handleObj(obj);
    } else {
        // 当前v1.0.0版本,不需要处理obj为null的情况
    }
}

这种方法就可以排除当初是忘记写else的情况,也对else的情况做了详细说明。

方案二、打印日志

注释可以避免省略else而导致的解读代码时疑惑,但在后面那种“可省略变成不可省略的情况”没有什么帮助,因为如果这个省略导致异常情况,那么直接原因可能在非常遥远的另一段代码中,而难以追踪到这里的根本原因,所以实际项目中,我们可以在else主体中打印日志,方便以后追踪问题:

void fun1(Object obj) {
    if (obj != null) {
        handleObj(obj);
    } else {
        Log.warn("预料之外的状况,请排查fun1中obj为null的情况");
    }
}

这样在项目更新迭代中,及时关注日志中的警告,可以提前发现一些隐患。

方案三、抛出异常

实际开发中,有时会比较仓促,就会忽略日志,这种情况就该考虑用更激进、严格的方式,也就是抛出异常:

void fun1(Object obj) {
    if (obj != null) {
        handleObj(obj);
    } else {
        throw new RuntimeException("不期望的状况,请排查fun1中obj为null的情况");
    }
}

这样就可以在测试阶段及早发现问题,并快速定位根源。

写在最后

  1. switch以及模式匹配的default行为类似。
  2. 关于防御性代码有更好的解决方案,待后期单独写文章来总结。