这些构造之间有什么区别以至于无法编译?
What is the difference between these constructs such that one won't compile?
一点背景故事(好吧,很多):我一直致力于创建采用 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 构造。我自己做了(NOT 复制了代码,只是复制了概念)而且效果非常好
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(ExceptionWrapper.java:39)
at crap.unk.ExceptionWrapper$$Lambda/1401420256.accept(Unknown Source)
...
Caused by: java.lang.Exception: 1
at crap.unk.ExceptionWrapper.lambda$main(ExceptionWrapper.java:54)
at crap.unk.ExceptionWrapper$$Lambda/501263526.accept(Unknown Source)
问题
为什么我最初的尝试不起作用?为什么使用具有相同结构的中介使其起作用?这似乎是由 throws
子句的差异引起的,但我不明白为什么。为什么它不同于将 Object
传递给方法并用 try/catch
包围调用?
您对 wrapConsumer
的初始尝试没有成功,因为它仍然使用 Consumer
作为参数,并且您尝试包装的 lambda 表达式仍然抛出 Exception
- - 检查异常。你的 try
/catch
离抛出的异常太远了,因为在你创建一个 lambda 表达式的时候,你已经在那里创建了一个 Consumer
,而 Consumer
's accept
method 不是t 声明抛出任何已检查的异常。
接受 ConsumerWrapper
的更改之所以有效,是因为该接口的方法声明允许它使用 throws Exception
抛出 Exception
。这允许您创建一个抛出检查异常的 lambda 表达式。
一点背景故事(好吧,很多):我一直致力于创建采用 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 构造。我自己做了(NOT 复制了代码,只是复制了概念)而且效果非常好
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(ExceptionWrapper.java:39) at crap.unk.ExceptionWrapper$$Lambda/1401420256.accept(Unknown Source) ... Caused by: java.lang.Exception: 1 at crap.unk.ExceptionWrapper.lambda$main(ExceptionWrapper.java:54) at crap.unk.ExceptionWrapper$$Lambda/501263526.accept(Unknown Source)
问题
为什么我最初的尝试不起作用?为什么使用具有相同结构的中介使其起作用?这似乎是由throws
子句的差异引起的,但我不明白为什么。为什么它不同于将 Object
传递给方法并用 try/catch
包围调用?
您对 wrapConsumer
的初始尝试没有成功,因为它仍然使用 Consumer
作为参数,并且您尝试包装的 lambda 表达式仍然抛出 Exception
- - 检查异常。你的 try
/catch
离抛出的异常太远了,因为在你创建一个 lambda 表达式的时候,你已经在那里创建了一个 Consumer
,而 Consumer
's accept
method 不是t 声明抛出任何已检查的异常。
接受 ConsumerWrapper
的更改之所以有效,是因为该接口的方法声明允许它使用 throws Exception
抛出 Exception
。这允许您创建一个抛出检查异常的 lambda 表达式。