最近看到自己以前写的代码,许多的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的状况");
}
}
写在最终
- switch以及模式匹配的default行为相似。
- 关于防御性代码有更好的解决计划,待后期独自写文章来总结。