抛出受检异常的方法引用声明时触发编译错误,求解决方案
解决带受检异常的方法引用存入函数式接口列表的问题
问题本质
Java标准库的Function<T,R>接口中,apply方法没有声明抛出受检异常,而你的方法都声明了throws InterruptedException(受检异常),直接将方法引用赋值给Function类型会触发编译错误——编译器要求受检异常必须被处理或显式声明抛出,但Function的方法签名不允许抛出这类异常。同时调用处的try/catch无效,因为此时编译器认为submitter.apply()不会抛出InterruptedException(Function的方法签名没声明)。
可行解决方案
方案1:自定义带受检异常的函数式接口
这是最贴合需求的方案,无需修改原有方法,只需定义一个适配受检异常的函数式接口:
@FunctionalInterface public interface ThrowingFunction<T, R> { // 声明允许抛出InterruptedException R apply(T t) throws InterruptedException; }
然后将列表的类型改为这个自定义接口:
final List<ThrowingFunction<Set<BookIdentifier>, Set<Status>>> submitters = List.of( this::submitIndividuallySynchronously, this::submitInBulkSynchronously, this::submitIndividuallyAsynchronously, this::submitInBulkAsynchronously);
调用时,因为接口方法明确声明了抛出受检异常,try/catch可以正常捕获:
final var submitter = submitters.get((isIndividual() ? 0 : 1) + (isSynchronous() ? 0 : 2)); try { result = submitter.apply(work.todo); } catch (final InterruptedException ex) { // 异常处理逻辑 }
方案2:包装方法引用,将受检异常转为非受检异常(可选)
如果不想自定义接口,可以将每个方法引用包装成Function,内部捕获受检异常并转为RuntimeException抛出(适合允许将受检异常转为非受检的场景):
final List<Function<Set<BookIdentifier>, Set<Status>>> submitters = List.of( ids -> { try { return submitIndividuallySynchronously(ids); } catch (InterruptedException e) { // 包装成非受检异常抛出 throw new RuntimeException(e); } }, ids -> { try { return submitInBulkSynchronously(ids); } catch (InterruptedException e) { throw new RuntimeException(e); } }, // 另外两个方法同理包装 );
调用时若需要处理异常,可捕获RuntimeException再还原原异常:
try { result = submitter.apply(work.todo); } catch (RuntimeException ex) { if (ex.getCause() instanceof InterruptedException ie) { // 处理InterruptedException逻辑 } else { throw ex; } }
内容的提问来源于stack exchange,提问作者davidbak
相关产品推荐
相关产品推荐

