背景:在一个方法中使用了lambda表达式,表达式中需要捕获异常,使用throws关键字发现并不起作用,必须使用trycatch才行
public class BeanUtil {
public static <T,R> List<R> copyList(List<T> source , Class<R> clazz) throws Exception {
if(CollectionUtils.isEmpty(source)){
return null;
}
List<R> rList = source.stream().map(s ->{
R r = null;
r = clazz.newInstance();
BeanUtils.copyProperties(s,r);
return r;
} ).collect(Collectors.toList());
return rList;
}
}
如上,虽然在方法copyList上使用了throws Exception但是已经无法通过编译,提示有未处理异常,正确代码如下,使用trycatch
try {
r = clazz.newInstance();
} catch (Exception e) {
e.printStackTrace();
}
提问:为何lambda表达式中的异常不能在外部throws,只能内部捕获?
看Stream.map(Function<? super T, ? extends R> mapper)方法,参数为Function实例,源码:
public final <R> Stream<R> map(Function<? super P_OUT, ? extends R> mapper) {
Objects.requireNonNull(mapper);
return new StatelessOp<P_OUT, R>(this, StreamShape.REFERENCE,
StreamOpFlag.NOT_SORTED | StreamOpFlag.NOT_DISTINCT) {
@Override
Sink<P_OUT> opWrapSink(int flags, Sink<R> sink) {
return new Sink.ChainedReference<P_OUT, R>(sink) {
@Override
public void accept(P_OUT u) {
downstream.accept(mapper.apply(u));
}
};
}
};
}
最终调用了Function中的apply方法,事实上,我们在map方法中写的s ->{……},其实就是重写apply方法的实现,而抛出异常的语句"r = clazz.newInstance()"就是在apply方法中抛出的,就是说在异常语句和copyList方法之间还存在一个apply方法,而apply方法是不允许向上抛出异常的,所以copyList方法自然不能使用throws抛异常。