这些结构之间有什么区别,以至于一个人不会编译?

时间:2015-06-05 20:13:40

标签: java lambda compilation java-8

一个小故事(好吧,很多):我一直致力于创建采用java.util.function类型的类,并使用try/catch块来执行它们的执行从lambda语句中删除使用try/catch的必要性。允许这个测试代码的东西:

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来调用?

1 个答案:

答案 0 :(得分:2)

wrapConsumer的初始尝试无效,因为它仍然需要Consumer作为参数,而您尝试换行的lambda表达式仍会引发Exception - - 检查异常。您的try / catch离抛出的异常太远,因为在您创建lambda表达式时,您已在那里创建ConsumerConsumer's accept method并未声明抛出任何已检查的异常。

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