Java 代码精简之道

作者:微信小助手

发布时间:2020-05-07T23:12:37


Photo @  Priscilla Du Preez 

文  |  常意



前言



古语有云:

道为术之灵,术为道之体;以道统术,以术得道。
其中:“道”指“规律、道理、理论”,“术”指“方法、技巧、技术”。意思是:“道”是“术”的灵魂,“术”是“道”的肉体;可以用“道”来统管“术”,也可以从“术”中获得“道”。

在拜读大佬“孤尽”的文章 《Code Review是苦涩但有意思的修行》 时,感受最深的一句话就是:“优质的代码一定是少即是多的精兵原则”,这就是大佬的代码精简之“道”。

工匠追求“术”到极致,其实就是在寻“道”,且离悟“道”也就不远了,亦或是已经得道,这就是“工匠精神”——一种追求“以术得道”的精神。如果一个工匠只满足于“术”,不能追求“术”到极致去悟“道”,那只是一个靠“术”养家糊口的工匠而已。作者根据多年来的实践探索,总结了大量的 Java 代码精简之“术”,试图阐述出心中的 Java 代码精简之“道”。


1.利用语法



1.1.利用三元表达式


普通:
 
String title;if (isMember(phone)) {    title = "会员";} else {    title = "游客";}

精简:
 
String title = isMember(phone) ? "会员" : "游客";

注意:对于包装类型的算术计算,需要注意避免拆包时的空指针问题。

1.2.利用 for-each 语句


从 Java 5 起,提供了 for-each 循环,简化了数组和集合的循环遍历。 for-each  循环允许你无需保持传统 for 循环中的索引就可以遍历数组,或在使用迭代器时无需在 while 循环中调用 hasNext 方法和 next 方法就可以遍历集合。

普通:
 
double[] values = ...;for(int i = 0; i < values.length; i++) {    double value = values[i];    // TODO: 处理value}
List<Double> valueList = ...;Iterator<Double> iterator = valueList.iterator();while (iterator.hasNext()) { Double value = iterator.next(); // TODO: 处理value}

精简:
 
double[] values = ...;for(double value : values) {    // TODO: 处理value}
List<Double> valueList = ...;for(Double value : valueList) { // TODO: 处理value}

1.3.利用 try-with-resource 语句


所有实现 Closeable 接口的“资源”,均可采用 try-with-resource 进行简化。

普通:
 
BufferedReader reader = null;try {    reader = new BufferedReader(new FileReader("cities.csv"));    String line;    while ((line = reader.readLine()) != null) {        // TODO: 处理line    }} catch (IOException e) {    log.error("读取文件异常", e);} finally {    if (reader != null) {        try {            reader.close();        } catch (IOException e) {            log.error("关闭文件异常", e);        }    }}

精简:
 
try (BufferedReader reader = new BufferedReader(new FileReader("test.txt"))) {    String line;    while ((line = reader.readLine()) != null) {        // TODO: 处理line    }} catch (IOException e) {    log.error("读取文件异常", e);}

1.4.利用 return 关键字


利用 return 关键字,可以提前函数返回,避免定义中间变量。

普通:
 
public static boolean hasSuper(@NonNull List<UserDO> userList) {    boolean hasSuper = false;    for (UserDO user : userList) {        if (Boolean.TRUE.equals(user.getIsSuper())) {            hasSuper = true;            break;        }    }    return hasSuper;}

精简:
 
public static boolean hasSuper(@NonNull List<UserDO> userList) {    for (UserDO user : userList) {        if (Boolean.TRUE.equals(user.getIsSuper())) {            return true;        }    }    return false;}

1.5.利用 static 关键字


利用 static 关键字,可以把字段变成静态字段,也可以把函数变为静态函数,调用时就无需初始化类对象。

普通:
 
public final class GisHelper {    public double distance(double lng1, double lat1, double lng2, double lat2) {        // 方法实现代码    }}

GisHelper gisHelper = new GisHelper();double distance = gisHelper.distance(116.178692D, 39.967115D, 116.410778D, 39.899721D);


精简:
public final class GisHelper {    public static double distance(double lng1, double lat1, double lng2, double lat2) {        // 方法实现代码    }}
double distance = GisHelper.distance(116.178692D, 39.967115D, 116.410778D, 39.899721D);


1.6.利用 lambda 表达式


Java 8 发布以后,lambda 表达式大量替代匿名内部类的使用,在简化了代码的同时,更突出了原有匿名内部类中真正有用的那部分代码。

普通:
 
new Thread(new Runnable() {    public void run() {        // 线程处理代码    }}).start();

精简:
 
new Thread(() -> {    // 线程处理代码}).start();

1.7.利用方法引用


方法引用(::),可以简化 lambda 表达式,省略变量声明和函数调用。

普通:
 
Arrays.sort(nameArray, (a, b) -> a.compareToIgnoreCase(b));List<Long> userIdList = userList.stream()    .map(user -> user.getId())    .collect(Collectors.toList());

精简:
Arrays.sort(nameArray, String::compareToIgnoreCase);List<Long> userIdList = userList.stream()    .map(UserDO::getId)    .collect(Collectors.toList());

1.8.利用静态导入