为什么我不能在Java 8 lambda表达式中抛出exception?
我升级到Java 8并试图用一个新的lamdba表达式替换一个简单的迭代迭代。 循环搜索空值并在找到exception时抛出exception。 旧的Java 7代码如下所示:
for (Map.Entry 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的快速修复建议看起来不对我…它只是用try-catch
块包围throw
语句:
myMap.forEach((k,v) -> { if(v == null) { try { throw new MyException("Key '" + k + "' not found!"); } catch (Exception e) { e.printStackTrace(); } } });
不允许抛出已检查的exception,因为java.util.function.BiConsumer
接口中的accept(T t, U u)
方法未在其throws
子句中声明任何exception。 而且,如您所知, Map#forEach
采用这种类型。
public interface Map { default void forEach(BiConsumer super K, ? super V> action) { ... } } | | V @FunctionalInterface public interface BiConsumer { void accept(T t, U u); // <-- does throw nothing }
当我们谈论检查exception时,情况就是如此。 但是你仍然可以抛出一个未经检查的exception(例如java.lang.IllegalArgumentException
):
new HashMap() .forEach((a, b) -> { throw new IllegalArgumentException(); });
你可以在lambdas中抛出exception。
允许lambda抛出与lambda实现的function接口相同的exception。
如果函数接口的方法没有throws子句,则lambda不能抛出CheckedExceptions。 (你仍然可以抛出RuntimeExceptions)。
在您的特定情况下, Map.forEach
使用BiConsumer
作为参数,BiConsumer定义为:
public interface BiConsumer { void accept(T t, U u); }
此function接口的lambda表达式不能抛出CheckedExceptions。
java.util.function
包中定义的函数接口中的方法不会抛出exception,但是您可以使用其他function接口或创建自己的接口以便能够抛出exception,即给定此接口:
public interface MyFunctionalInterface { void accept(T t) throws Exception; }
以下代码是合法的:
MyFunctionalInterface f = (s)->throw new Exception("Exception thrown in lambda");
- 在预期时处理NumberFormatException的正确方法是什么?
- 如何从未经检查的exception中恢复?
- 如果服务器返回错误状态,java.net.HttpUrlConnection是否总是抛出IOException?
- 调试时强制exception
- 线程“AWT-EventQueue-0”中的exceptionjava.lang.ClassCastException:javax.swing.JTable
- 既不是BindingResult也不是普通的目标对象……例外
- Android SQLite如何获取特定列:行值
- 为什么我需要处理Thread.sleep()的exception?
- java.lang.IllegalStateException:在servlet中提交响应后无法转发