【问题标题】:What is the difference between these constructs such that one won't compile?这些构造之间有什么区别,以至于无法编译?
【发布时间】:2015-06-05 20:13:40
【问题描述】:

一点背景故事(好吧,很多):我一直致力于创建采用 java.util.function 类型的类,并用 try/catch 块包装它们的执行以消除使用 @ 987654325@ 来自 lambda 语句。允许这个测试代码的东西:

list.forEach(ExceptionWrapper.wrapConsumer(s -> {throw new Exception(s);}));

在这样做的过程中,我想出了这个。它确实没有工作。

public class ExceptionWrapper {
    public static <T> Consumer<T> wrapConsumer(Consumer<T> consumer){
        return t -> {
            try {
                consumer.accept(t);
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        };
    }
}

许多咒语总是导致

Error:(54, 61) java: unreported exception java.lang.Exception; must be caught or declared to be thrown

经过大量搜索,我发现了jOOλ 代码。它看起来几乎相同,只是它们使用了一个模仿包装类型但声明抛出异常的中间 lambda 构造。我自己做了(没有复制了代码,只是复制了概念)而且效果非常棒

public interface ConsumerWrapper<T>{
    void accept(T t) throws Exception;
}

并在 ExceptionWrapper 中进行更改

    public static <T> Consumer<T> wrapConsumer(ConsumerWrapper<T> consumer){
        ...                                        //  ^ note change
    }

允许编译和运行初始测试代码。

public static void main(String[] args) {
    List<String> strings = Arrays.asList("1");
    strings.forEach(System.out::println);
    strings.forEach(ExceptionWrapper.wrapConsumer(s -> {throw new Exception(s);}));
}
线程“main”中的异常 java.lang.RuntimeException: java.lang.Exception: 1
    在 crap.unk.ExceptionWrapper.lambda$wrapConsumer$2(ExceptionWrapper.java:39)
    在 crap.unk.ExceptionWrapper$$Lambda$3/1401420256.accept(未知来源)
...
引起:java.lang.Exception:1
    在 crap.unk.ExceptionWrapper.lambda$main$3(ExceptionWrapper.java:54)
    在 crap.unk.ExceptionWrapper$$Lambda$2/501263526.accept(未知来源)

问题

为什么我最初的尝试不起作用?为什么使用具有相同结构的中介使其起作用?这似乎是由 throws 子句的差异引起的,但我不明白为什么。为什么它不同于将Object 传递给方法并用try/catch 包围调用?

【问题讨论】:

  • 顺便说一句,你不需要包装异常,你可以throw checked exceptions as unchecked。添加一些转换器来抛出消费者/功能/供应商等的等价物,它应该简化流处理

标签: java lambda compilation java-8


【解决方案1】:

您对wrapConsumer 的初始尝试没有成功,因为它仍然将Consumer 作为参数,并且您尝试包装的lambda 表达式仍然抛出Exception - 已检查异常。您的 try/catch 距离抛出的异常太远了,因为在您创建 lambda 表达式时,您已经在那里创建了一个 Consumer,并且 Consumer's accept method 没有声明为抛出任何已检查的异常。

接受ConsumerWrapper 的更改有效,因为该接口的方法声明允许它使用throws Exception 抛出Exception。这允许您创建一个引发检查异常的 lambda 表达式。

【讨论】:

  • "在您创建 lambda 表达式时,您已经在那里创建了一个 Consumer,并且 Consumer 的 accept 方法没有声明为抛出任何已检查的异常。" 这是对我有帮助的声明。我想我现在看到了编译流程。我仍然习惯于思考函数结构以及它们是如何被解释的。
猜你喜欢
  • 1970-01-01
  • 2013-11-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多