一、前言
Lambda 表达式 在日常开发过程中实在是太方便了,功能强大且简化了很多代码。但是遇上编译时异常时候却很尴尬。由于Lambda无法抛出异常,导致你必须要对异常进行捕获。这样写起来的点就很丑。本篇针对这个问题进行了一些改进。
二、示例
- 一个简单的集合遍历如下:
public static void main(String[] args) {
List<User> list = new ArrayList<>();
list.add(new User(1, "张三", "123"));
list.add(new User(2, "李四", "321"));
list.stream().forEach(user -> System.out.println(user.info()));
}
...
// user类
public class User {
private int id;
private String name;
private String pwd;
...省略get、set和构造函数
public String info() {
return "User{" +
"id=" + id +
", name='" + name + '\'' +
", pwd='" + pwd + '\'' +
'}';
}
}
一句话完成了集合遍历,十分方便。但是如果我们让info抛出一个编译时异常,假设是 IOException。
那么我们就没那么简单遍历了。我们必须要捕获这个IOException 。代码变成了如下形式。
public static void main(String[] args) {
List<User> list = new ArrayList<>();
list.add(new User(1, "张三", "123"));
list.add(new User(2, "李四", "321"));
list.stream().forEach(user -> {
try {
System.out.println(user.info());
} catch (IOException e) {
e.printStackTrace();
}
});
}
...
// user类
public class User {
private int id;
private String name;
private String pwd;
...省略get、set和构造函数
public String info() throws IOException{
return "User{" +
"id=" + id +
", name='" + name + '\'' +
", pwd='" + pwd + '\'' +
'}';
}
}
那么这个流操作就很难受,明明我的业务逻辑很简单,但是却需要写一个try…catch。其实写了也无所谓,关键是代码变丑了!代码变丑了!代码变丑了!
- 所以我们想到可以将编译时异常转为运行时异常抛出。
Stream.forEach() 方法如下。可以看到forEach方法并没有抛出异常,从而导致我们在调用forEach时只能在内部捕获异常:
void forEach(Consumer<? super T> action);
所以我们可以自定义一个MyConsumer接口,抛出异常,如下:
public interface MyConsumer<T> {
void apply(T t) throws Throwable;
}
可是光抛出异常没用,我们需要转换异常结构。所以再定义一个接口来进行一个代理(或者说委托,或者说其它,以我的能力,我还没分清 )。我们通过接口回调来处理消息。
public interface Lambda {
static <T> Consumer<T> forEach(MyConsumer<T> myConsumer){
// return new Consumer<T>() {
// @Override
// public void accept(T t) {
// try {
// myConsumer.apply(t);
// } catch (Throwable throwable) {
// throw new RuntimeException(throwable);
// }
// }
// };
return t -> {
try {
myConsumer.apply(t);
} catch (Throwable throwable) {
throw new RuntimeException(throwable);
}
};
};
}
调用就可以变成如下形式,不用再捕获异常了:
public static void main(String[] args) {
List<User> list = new ArrayList<>();
list.add(new User(1, "张三", "123"));
list.add(new User(2, "李四", "321"));
list.stream().forEach(Lambda.forEach(user -> System.out.println(user.info())));
}
同理再写一个map
public interface MyFunction<T, R> {
R apply(T t) throws Throwable;
}
public interface Lambda {
static <T> Consumer<T> forEach(MyConsumer<T> myConsumer){
return t -> {
try {
myConsumer.apply(t);
} catch (Throwable throwable) {
throw new RuntimeException(throwable);
}
};
};
static <T, R> Function<T, R> map(MyFunction<T, R> myFunction){
return t -> {
try {
return myFunction.apply(t);
} catch (Throwable throwable) {
throw new RuntimeException(throwable);
}
};
}
}
调用如下:
扫描二维码关注公众号,回复:
11960637 查看本文章
public static void main(String[] args) {
List<User> list = new ArrayList<>();
list.add(new User(1, "张三", "123"));
list.add(new User(2, "李四", "321"));
// 改造前
list.stream().forEach(user -> {
try {
System.out.println(user.info());
} catch (IOException e) {
e.printStackTrace();
}
});
// 改造后
list.stream().forEach(Lambda.forEach(user -> System.out.println(user.info())));
// 改造前
list.stream().map(user -> {
try {
return user.info();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}).collect(Collectors.toList());
// 改造后
list.stream().map(Lambda.map(user -> user.info())).collect(Collectors.toList());
}
三、总结
本篇只作为一个引子,记录一下使用方式。至于后续的通用性扩展,就不再展开。
以上:内容部分参考
https://mp.weixin.qq.com/s/Dvd13G7UE5Zz5gQxlUkiFQ
如有侵扰,联系删除。 内容仅用于自我记录学习使用。如有错误,欢迎指正