代码优雅之道:简化异常处理语句
先来个实际效果
写代码时难免会遇到异常, 对待异常有的时候直接抛出, 有的时候需要实际的处理, 例如下面这个
MessageDigest 里面是有MD5方法的, 那么这个异常完全没必要, 那就在方法内部对异常进行处理, 然后就变成了下面这样.
/**
* 获取一个byte[]的md5值
*
* @param data 待转换的数据
* @return md5 byte[]的MD5值
*/
public static String getMD5(byte[] data) {
MessageDigest md5;
try {
md5 = MessageDigest.getInstance("MD5");
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException("MessageDigest 未发现 MD5 方法", e);
}
byte[] digest = md5.digest(data);
return new BigInteger(1, digest).toString(16);
}
本来三行就能写好的代码, 因为个异常处理变得臃肿, 难看, 那么有没有办法把它变得优雅呢?
答案肯定有, 否则就不会有这篇文章了!
为了节省大家的时间, 首先来展示下优化后的代码.
/**
* 获取一个byte[]的md5值
*
* @param data 待转换的数据
* @return md5 byte[]的MD5值
*/
public static String getMD5(byte[] data) {
final MessageDigest md5 = Throws.fun("MD5", MessageDigest::getInstance).runtimeExp("MessageDigest 未发现 MD5 方法").value();
byte[] digest = md5.digest(data);
return new BigInteger(1, digest).toString(16);
}
3行搞定真是很开心!
其实不只是上面的优化, 也能做到下面几组的优化
第一组优化
// 源代码
String s = null;
try {
s = ConfigTest.newHaha();
} catch (NoSuchMethodException e) {
log.error("", e);
}
// == SimpleCode优化
String s = SimpleCode.ignoreException(ConfigTest::newHaha);
// == Throws 优化
String s = Throws.sup(ConfigTest::newHaha).logThrowable().value();
第二组优化
try {
AppContext.init()
} catch (ConfigException e) {
e.printStackTrace();
}
// 等价于
Throws.con(100, AppContext::init).catchToPrintStackTrace();
// 或等价于
Throws.run(() -> AppContext.init()).catchToPrintStackTrace();
异常语句优化思路
在写工具类的时候, 很多情况下, 对异常的处理也就是个打印现场
工作, 即便写业务类也就是个打印现场
, 既然工作都差不多, 那就可以想办法封装起来, 优化代码, 又便于阅读.
首先, 说到封装try catch
, 能够想到的就是函数式接口
和lambda表达式
, 这真是JAVA的两大神器啊!
然后, JDK自带的函数式接口是没有办法处理异常的, 那就把之前说到的几个带有异常抛出的几个函数式接口拿出来.
那么, 就很容易想到一种方式, 通过静态方法, 将lambda表达式当作参数传进去, 在静态方法里面处理异常, 这样就可以简化异常的代码.
其次, 讲到 try catch
比较好的处理方式, 我想到的是JS里面的 Promise
, 它的处理方式给我带来了很多灵感.
接下来, 就通过代码实际操作一下吧!
异常语句优化方式1-静态方法优化
由于涉及到好几个lambda表达式的优化, 整体代码较多, 下面只是展示下 SupplierWithThrow 的优化方式
RunnableWithThrow : 带有抛出异常的 Runnable 接口