2 年前,我在 b 站上录制了一个视频,如何优雅的干掉 if else。我当时提出了“断言”+“短路”的形式,最直接的干掉 if else。很多人非常受益,今天我再整理成文字分享给大家!
if else 是我们写代码时,使用频率最高的关键词之一,然而有时过多的 if else 会让我们感到脑壳疼,例如下面这个伪代码:
是不是很奔溃?想象你现在是一个新手程序员,或者是一个刚入职的小司机,这样的代码,你敢维护吗?
基于此,我在这里推荐几种消除 if else 的方法,希望能够帮助到大家!
多使用“断路”return
if("".equals(author)){
// ...
System.out.println("你好");
}else if("大佬".equals(author)){
// ...
System.out.println("你好");
} else {
throw new Exception("error");
}
上面这么代码,我们这样这样修改:
if("".equals(author)){
// ...
System.out.println("你好");
return;
}
if("大佬".equals(author)){
// ...
System.out.println("你好");
return;
}
throw new Exception("error");
当然,我这个案例嵌套的层次太少,部分人感觉不明显。下面我们一起看一个稍微复杂一点的案例。
public String getTweetTitle(int type) {
String result;
if (type == 0) {
throw new IllegalArgumentException("参数有误");
}
//长贴-->获得长帖标题
if (isPaperTweet(type)) {
result = getPaperTweetTitle();
} else {
// 视频贴-->获得视频贴标题
if (isVideoTweet(type)) {
result = getVideoTitle();
} else {
result = getDefaultTitle();
}
}
return result;
}
我们使用“断路”的方法,可以改成如下方式:
public String getTweetTitle(int type) {
// 条件检查
if (type == 0) {
throw new IllegalArgumentException("参数有误");
}
// 长贴-->获得长帖标题
if (isPaperTweet(type)) {
return getPaperTweetTitle();
}
// 视频贴-->获得视频贴标题
if (isVideoTweet(type)) {
return getVideoTitle();
}
return getDefaultTitle();
}
上面的代码是不是看起来更清爽一些!实际上,阿里巴巴开发手册中也推荐我这种做法了!
减少无用的 if else
我们继续接着看一个例子:
if(100 == age){
return true;
} else {
return false;
}
这是我工作多年来,见到不少同事这样写的(不是故意黑他们)。
我们可以这样改:
return 100 == age;
直接返回判断的结果。
使用三元运算
实际上,从效率上来讲,三元运算的效率也比 if else 高!
if(age > 18){
result = "成年人可以打游戏超过1个小时";
} else {
result = "未成年人打游戏不能超过1个小时";
}
改成三元运算:
result = age > 18 ? "成年人可以打游戏超过1个小时" : "未成年人打游戏不能超过1个小时";
多使用断言
继续看下面这个例子:
if(null == name || "".equals(name)){
throw new Exception("姓名不能为空");
}
if(age < 18){
throw new Exception("年龄不能小于18");
}
我们可以改成下面的实现:
Assert.hasLength(name, "姓名不能为空");
Assert.isTrue(age < 18, "年龄不能小于18");
或者是你自己封装一个参数校验方法。
public abstract class PreCheck {
public PreCheck() {
}
public static void preCheckNotNull(Object obj) {
if (obj == null) {
throw new ServerException("attr data cannot be empty");
}
}
public static void preCheckNotNull(Object obj, String msg) {
if (obj == null) {
throw new ServerException(msg);
}
}
public static void preCheckNotNull(Object obj, ErrorMessage errorMessage) {
if (obj == null) {
throw new ServerException(errorMessage);
}
}
public static void preCheckArgument(boolean checked, String msg) {
if (checked) {
throw new ServerException(msg);
}
}
public static void preCheckArgument(boolean checked, ErrorMessage errorMessage) {
if (checked) {
throw new ServerException(errorMessage);
}
}
public static BigDecimal preCheckBigDecimal(String val, String msg) {
try {
return new BigDecimal(val);
} catch (Exception var3) {
throw new ServerException(msg);
}
}
public static BigDecimal preCheckBigDecimal(String val, ErrorMessage errorMessage) {
try {
return new BigDecimal(val);
} catch (Exception var3) {
throw new ServerException(errorMessage);
}
}
// ...
}
上面这个是我常用的一个工具类。
使用 map 取代 if else
if (t == 1) {
type = "百度";
} else if (t == 2) {
type = "字节";
} else if (t == 3) {
type = "阿里";
} else if (t == 4) {
type = "腾讯";
}
// ...
如果 if 太多,就显得太长了。我见过一个 if else if 超过 300 行的代码。这个时候三元运算符也不太好用了,这里我推荐使用 map 来做。
Map<Integer, String> typeMap = new HashMap<>();
typeMap.put(1, "百度");
typeMap.put(2, "字节");
typeMap.put(3, "阿里");
typeMap.put(4, "腾讯");
// ...
return typeMap.get(type);
减少没必要的 if
一些代码我们要合理的抽取,提出公共的部分。下面我们再看一个例子:
String result = "";
if(age == 1){
// todo
result = "年龄太小了";
}
if(age == 2){
// todo
result = "年龄太小了";
}
// ...
上面的代码我们可以将两个 if 进行合并。
String result = "";
if(age == 1 || age == 2){
// todo
result = "年龄太小了";
}
// ...
当然,如果是一个范围,也可以进行范围判断。
String result = "";
if(age > 0 || age < 12){
// todo
result = "年龄太小了";
}
// ...
反向逻辑减少 if else
多数情况下,我们写代码都是正向逻辑。下面我通过一些反向逻辑减少一些 if else。
// 方法 A
List<DocFieldDto> list = dto.getDocFieldDtoList();
if (!CollectionUtils.isEmpty(list)) {
// todo ...
}
// 方法 B
if(a != null){
// todo
if(b != null){
// todo
}
}
我们可以利用反向逻辑进行代码精简改造!
// 方法 A
List<DocFieldDto> list = dto.getDocFieldDtoList();
if(CollectionUtils.isEmpty(list)){
return;
}
// 方法 B
if(null == a){
return;
}
// todo
if(b == null){
return;
}
// todo
多使用 Optional
Optional 还是很好用的,我个人非常喜欢用。继续看下面这个例子:
String str = "java和前端都难";
if (str == null) {
System.out.println("null");
} else {
System.out.println(str);
}
我们可以这样改:
String str2 = "java和前端都难";
String result = Optional.ofNullable(str2).orElse("null");
System.out.println(result);
//输出:java和前端都难
//等同于:
if (str2 != null) {
System.out.println(str2);
} else {
System.out.println("null");
}
再比如,我们通常有一个对象,需要一层一层的去判断取值。
String isocode = user.getAddress().getCountry().getIsocode().toUpperCase();
// 或者有些程序员加上了判断
if (user != null) {
Address address = user.getAddress();
if (address != null) {
Country country = address.getCountry();
if (country != null) {
String isocode = country.getIsocode();
if (isocode != null) {
isocode = isocode.toUpperCase();
}
}
}
}
如果用 Optional,看起来就更舒服了。
@Test
public void whenChaining_thenOk() {
User user = new User("anna@gmail.com", "1234");
String result = Optional.ofNullable(user)
.flatMap(u -> u.getAddress())
.flatMap(a -> a.getCountry())
.map(c -> c.getIsocode())
.orElse("default");
assertEquals(result, "default");
}
也可以通过方法引用进一步缩减:
String result = Optional.ofNullable(user)
.flatMap(User::getAddress)
.flatMap(Address::getCountry)
.map(Country::getIsocode)
.orElse("default");
当然,Optional 在某些场景下是不能够完全代替 if else 的,这点视情况自行判断。
以上就是我们经常使用的缩减 if else 的小妙招。不喜轻喷!
除此之外,很多人可能还看到过各种设计模式干掉 if else 的,我就不多说了。包括:多态、反射、枚举、策略模式等不在本文的讨论范围内。
: » 收藏!简单且优雅的8种干掉if else的方法(非设计模式方法)
原创文章,作者:wure,如若转载,请注明出处:https://blog.ytso.com/251415.html