java - 这些构造之间有什么区别,以至于无法编译?

标签 java lambda compilation java-8

一些背景故事(好吧,很多):我一直在致力于创建需要 java.util.function 的类。类型并用 try/catch 包装它们的执行 block 以消除使用 try/catch 的需要从 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);}));
}
Exception in thread "main" java.lang.RuntimeException: java.lang.Exception: 1
    at crap.unk.ExceptionWrapper.lambda$wrapConsumer$2(ExceptionWrapper.java:39)
    at crap.unk.ExceptionWrapper$$Lambda$3/1401420256.accept(Unknown Source)
...
Caused by: java.lang.Exception: 1
    at crap.unk.ExceptionWrapper.lambda$main$3(ExceptionWrapper.java:54)
    at crap.unk.ExceptionWrapper$$Lambda$2/501263526.accept(Unknown Source)

问题

为什么我最初的尝试不起作用?为什么使用具有相同结构的中介可以使其发挥作用?这似乎是由 throws 的差异引起的条款,但我不明白为什么。为什么它与传递 Object 不同?转到方法并用 try/catch 包围调用?

最佳答案

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

接受 ConsumerWrapper 的更改之所以有效,是因为该接口(interface)的方法声明允许它抛出 Exception,其中 throws Exception。这允许您创建一个引发已检查异常的 lambda 表达式。

关于java - 这些构造之间有什么区别,以至于无法编译?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30675052/

相关文章:

java - 为什么不在 JavaFX Controller 中注入(inject)成员?

java - Servlet 编码重定向URL

c++ - 什么时候评估 lambda 函数中的表达式?

c# - 为什么必须将变量值建模为对表达式树中闭包的成员访问?

javascript - 从字符串转换为 lambda

c - 定义一个C程序编译后要修改的地址

c - 如何修复对膨胀/收缩函数的 undefined reference ?

java - 如何使用按钮启动和停止旋转 ImageView 的动画

java - 三维数组的替代方案

java - 运行引用 OpenCV 的 Jar 文件的 Java 程序