不知你有没有被多层嵌套的 if-else 语句所折磨过,就像下面这种 “横放着的金字塔”:
if(true){
if(true){
if(true){
if(true){
if(true){
if(true){
}
}
}
}
}
}
实际项目中你要是真敢这样写,保证你过几天就忘了这里面的逻辑是什么。一开始一顿操作猛如虎,到后来怀疑自己二百五。
其实我们仔细看看上面的判断语句,它们都是在 if 里面的条件是真的情况才执行,也就是说它们都是走的正常情况,才会导致这么无限嵌套下去,那么我们从反面思考是不是就可以终止这种情况呢?也就是我们把不正常的条件先摘出来处理,剩下的就都是正常情况了。这其实就是卫语句的思考模式,也就是逆向思考。卫语句可以减少 if-else 语句嵌套的情况出现。所以在阿里巴巴 Java 规范里也写到 “多层条件语句建议使用卫语句、策略模式、状态模式等方式重构。”
为了让大家对卫语句有一个直观的认识,我将给大家举一个例子。if-else 语句一般在 for 循环里面使用,用于分支控制,如求 100 以内同时是 3、4、5 的倍数的题,如果我们根据题目所说的老老实实地判断符合倍数的情况,将会写成这样(假设每个 if 语句只判断一个条件):
for (int i = 1; i <= 100; i++) {
if (i%3 == 0){
if (i%4 == 0){
if (i%5 == 0){
System.out.println(i);
}
}
}
}
这就是前面说的 “横放着的金字塔”,而如果我们逆向思考,从是 3、4、5 的倍数的反面思考,也就是哪些情况不是 3、4、5 的倍数,先把这些情况摘出来,然后结束本次循环,继续找下一个数。这样我们就能防止多层嵌套了:
for (int i = 1; i <= 100; i++) {
if (i%3 != 0){
continue;
}
if (i%4 != 0){
continue;
}
if (i%5 != 0){
continue;
}
System.out.println(i);
}
只有在上面三个条件都不成立的情况下,才会走到最后一步输出的语句。也就是排除那些不符合条件的情况,剩下的自然就是符合条件的了。希望通过这个小例子能让你明白到底什么是卫语句。
其实在写这篇文章之前我也在网上搜了一下什么是卫语句,但都没有讲到精髓上,大都是举一个例子,然后举一个反例,没有提高到思考模式上来。这样你也只是会这一个例子,如果换了一个你可能又不会了。所以我总结了一下,决定写一遍讲卫语句背后的思考模式的文章,希望大家真正掌握这个编程方式。虽然给大家解释了什么是卫语句,但是这种逆向思维模型的 if-else 语句为什么叫卫语句我还没有找到出处,可能它就是保卫代码不臃肿吧。