【问题标题】:Catch RuntimeException thrown in a lambda and rethrow it as checked捕获在 lambda 中抛出的 RuntimeException 并将其重新抛出为选中状态
【发布时间】:2014-04-09 09:42:54
【问题描述】:

我试图弄清楚为什么我的代码会抛出 IllegalStateException,而不是我希望它抛出的自定义代码。

public final class CollectorUtils {
    private CollectorUtils() {
        throw new UnsupportedOperationException();
    }

    public static <E, R, X extends Throwable> Collector<E, ?, R> listAndThenCollector(final Predicate<List<E>> listPredicate, final Function<List<E>, R> listFunction, final Function<Throwable, X> exceptionWrapper) throws X {
        Objects.requireNonNull(listPredicate);
        Objects.requireNonNull(listFunction);
        Objects.requireNonNull(exceptionWrapper);
        try {
            return Collectors.collectingAndThen(Collectors.toList(), list -> {
                if (!listPredicate.test(list)) {
                    throw new IllegalStateException(); //Line that throws the exception
                }
                return listFunction.apply(list);
            });
        } catch (IllegalStateException ex) {
            throw exceptionWrapper.apply(ex);
        }
    }

    public static <E> Collector<E, ?, E> singleElementCollector() throws NotASingleElementException {
        return listAndThenCollector(list -> list.size() == 1, list -> list.get(0), NotASingleElementException::new);
    }
}

IllegalStateException 被抛出:throw new IllegalStateException()

示例用法:

public static void test() {
    try {
        Integer result = IntStream.range(0, 2)
                .boxed()
                .collect(CollectorUtils.singleElementCollector());
    } catch (NotASingleElementException ex) {
        Logger.getLogger(CollectorUtils.class.getName()).log(Level.SEVERE, null, ex);
    }
}

这段代码应该抛出一个NotASingleElementException,而不是抛出一个IllegalStateException,我怎样才能让它工作?

执行实际工作时的错误行为:

Exception in thread "pool-3-thread-1" java.lang.IllegalStateException
    at dpc2.base.utils.CollectorUtils.lambda$listAndThenCollector$0(CollectorUtils.java:28)
    at dpc2.base.utils.CollectorUtils$$Lambda$21/2071035411.apply(Unknown Source)
    at java.util.function.Function.lambda$andThen$6(Function.java:88)
    at java.util.function.Function$$Lambda$22/63121782.apply(Unknown Source)
    at java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:503)
    at dpc2.base.utils.ImageMagickUtils.convertPDFToTIFF(ImageMagickUtils.java:30)
    at dpc2.server.convert.ConvertConsumer.accept(ConvertConsumer.java:20)
    at dpc2.server.convert.ConvertConsumer.accept(ConvertConsumer.java:14)
    at dpc2.base.checker.BaseChecker.lambda$null$0(BaseChecker.java:116)
    at dpc2.base.checker.BaseChecker$$Lambda$15/2121862243.run(Unknown Source)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
    at java.lang.Thread.run(Thread.java:744)

【问题讨论】:

  • 源代码块中的哪一行是CollectorUtils.java:28
  • @T.J.Crowder 那是throw new IllegalStateException()
  • @skiwi:你应该更新问题,说这是行。 (请确保确实如此,有时我们会假设一些事情,但如果我们真正检查,我们会意识到我们误导了自己。)
  • 修正了一个重要的错字:应该是list -&gt; list.size() == 1

标签: java exception exception-handling lambda java-8


【解决方案1】:

您的收集器已返回,但未在 listAndThenCollector 方法中收集。实际收集发生在:

.collect(CollectorUtils.singleElementCollector());

在您的测试方法中。这就是抛出异常的时候。

【讨论】:

  • 而此时IllegalStateException 已经被抛出,因此要从中恢复为时已晚。我可能需要使用自定义未经检查的异常。
【解决方案2】:

我会说这是因为当您调用 Collectors.collectingAndThen 时,您会传递一个当时不执行的 lambda。当它最终执行时,您的 catch 将不再存在。

你不能使用:

//throw new IllegalStateException();
throw exceptionWrapper.apply(new IllegalStateException());

【讨论】:

    猜你喜欢
    • 2021-10-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-01-15
    • 2010-10-27
    • 1970-01-01
    • 2013-10-04
    • 1970-01-01
    相关资源
    最近更新 更多