为什么我不能在 Java 8 lambda 表达式中抛出异常?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/37726874/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Why can't I throw an exception in a Java 8 lambda expression?
提问by dokaspar
I upgraded to Java 8 and tried to replace a simple iteration through a Map with a new lamdba expression. The loop searches for null values and throws an exception if one is found. The old Java 7 code looks like this:
我升级到 Java 8 并尝试用新的 lamdba 表达式替换通过 Map 的简单迭代。循环搜索空值并在找到时抛出异常。旧的 Java 7 代码如下所示:
for (Map.Entry<String, String> entry : myMap.entrySet()) {
if(entry.getValue() == null) {
throw new MyException("Key '" + entry.getKey() + "' not found!");
}
}
And my attempt to convert this to Java 8 looks like this:
我将其转换为 Java 8 的尝试如下所示:
myMap.forEach((k,v) -> {
if(v == null) {
// OK
System.out.println("Key '" + k+ "' not found!");
// NOK! Unhandled exception type!
throw new MyException("Key '" + k + "' not found!");
}
});
Can anyone explain why the throw
statement not allowed here and how this could be corrected?
谁能解释为什么throw
这里不允许声明以及如何更正?
Eclipse's quick-fix suggestion does not look right to me... it simply surrounds the throw
statement with a try-catch
block:
Eclipse 的快速修复建议在我看来并不正确......它只是throw
用一个try-catch
块包围了语句:
myMap.forEach((k,v) -> {
if(v == null) {
try {
throw new MyException("Key '" + k + "' not found!");
}
catch (Exception e) {
e.printStackTrace();
}
}
});
采纳答案by Andrew Tobilko
You are not allowed to throw checked exceptions because the accept(T t, U u)
method in the java.util.function.BiConsumer<T, U>
interface doesn't declare any exceptions in its throws
clause. And, as you know, Map#forEach
takes such a type.
不允许抛出已检查的异常,因为接口中的accept(T t, U u)
方法java.util.function.BiConsumer<T, U>
没有在其throws
子句中声明任何异常。而且,如您所知,Map#forEach
采用这种类型。
public interface Map<K, V> {
default void forEach(BiConsumer<? super K, ? super V> action) { ... }
} |
|
V
@FunctionalInterface
public interface BiConsumer<T, U> {
void accept(T t, U u); // <-- does throw nothing
}
That is true when we are talking about checked exceptions. But you still can throw an unchecked exception (e.g. a java.lang.IllegalArgumentException
):
当我们谈论受检异常时,确实如此。但是您仍然可以抛出未经检查的异常(例如 a java.lang.IllegalArgumentException
):
new HashMap<String, String>()
.forEach((a, b) -> { throw new IllegalArgumentException(); });
回答by David SN
You can throw exceptions in lambdas.
您可以在 lambda 表达式中抛出异常。
A lambda is allowed to throw the same exceptions as the functional interface implemented by the lambda.
lambda 被允许抛出与 lambda 实现的函数接口相同的异常。
If the method of the functional interface doesn't have a throws clause, the lambda can't throw CheckedExceptions. (You still can throw RuntimeExceptions).
如果函数式接口的方法没有 throws 子句,则 lambda 不能抛出 CheckedExceptions。(您仍然可以抛出 RuntimeExceptions)。
In your particular case, Map.forEach
uses a BiConsumer
as a parameter, BiConsumer is defined as:
在您的特定情况下,Map.forEach
使用 aBiConsumer
作为参数, BiConsumer 定义为:
public interface BiConsumer<T, U> {
void accept(T t, U u);
}
A lambda expression for this functional interface can't throw CheckedExceptions.
此函数式接口的 lambda 表达式不能抛出 CheckedExceptions。
The methods in the functional interfaces defined in java.util.function
package don't throw exceptions, but you can use other functional interfaces or create your own to be able to throw exceptions, i.e. given this interface:
java.util.function
包中定义的函数式接口中的方法不会抛出异常,但是您可以使用其他函数式接口或创建自己的能够抛出异常的方法,即给定这个接口:
public interface MyFunctionalInterface<T> {
void accept(T t) throws Exception;
}
The following code would be legal:
以下代码是合法的:
MyFunctionalInterface<String> f = (s)->throw new Exception("Exception thrown in lambda");