我升级到Java 8并尝试使用新的lamdba表达式替换一个简单的迭代迭代。循环搜索空值并在找到异常时抛出异常。旧的Java 7代码如下所示:
for (Map.Entry<String, String> entry : myMap.entrySet()) {
if(entry.getValue() == null) {
throw new MyException("Key '" + entry.getKey() + "' not found!");
}
}
我将此转换为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!");
}
});
有人可以解释为什么这里不允许throw
声明,以及如何纠正这个声明?
Eclipse的快速修复建议对我来说不合适......它只是用throw
块围绕try-catch
语句:
myMap.forEach((k,v) -> {
if(v == null) {
try {
throw new MyException("Key '" + k + "' not found!");
}
catch (Exception e) {
e.printStackTrace();
}
}
});
答案 0 :(得分:45)
由于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
}
当我们谈论检查异常时,这是真的。但你仍然可以抛出一个未经检查的异常(例如java.lang.IllegalArgumentException
):
new HashMap<String, String>()
.forEach((a, b) -> { throw new IllegalArgumentException(); });
答案 1 :(得分:25)
你可以在lambdas中抛出异常。
允许lambda抛出与lambda实现的功能接口相同的异常。
如果函数接口的方法没有throws子句,则lambda不能抛出CheckedExceptions。 (你仍然可以抛出RuntimeExceptions。)
在您的特定情况下,kombu
使用concurrent.futures.ThreadPoolExecutor
作为参数,BiConsumer定义为:
Map.forEach
此功能接口的lambda表达式不能抛出CheckedExceptions。
BiConsumer
包中定义的功能接口中的方法不会抛出异常,但是您可以使用其他功能接口或创建自己的接口以便能够抛出异常,即给定此接口:
public interface BiConsumer<T, U> {
void accept(T t, U u);
}
以下代码是合法的:
java.util.function