为什么我们不能在Java 8流中抛出异常?

时间:2017-03-11 18:43:15

标签: java-8 java-stream

E.g:

Person result = persons.stream()
                  .filter(x -> {
                    if ("test".equals(x.getName() ) ) {
                      throw new IOException("not possible inside stream y ?"); //any checked exception
                    }
                    //code here
                  })

M寻找不被允许的理由?即使声明代码的方法也抛出IOException

2 个答案:

答案 0 :(得分:5)

你的代码工作正常,除了throw new ...行末尾缺少一个半冒号,以及缺少一个可能隐藏在// code here中的return语句。

您可以做的是抛出一个已检查的异常(RuntimeException不是),因为已检查的异常是方法签名的一部分,并且Predicate.test方法不会声明一个。

编辑: 为了更准确地看到发生了什么以及为什么你不能在这里抛出一个检查过的异常,下面是你如何编写没有lambda的代码:

由此:

public Person myMethod() throws IOException {
    Person result = persons.stream()
              .filter(x -> {
                if ("test".equals(x.getName() ) ) {
                  throw new IOException("not possible inside stream y ?"); //any checked exception
                }
                //code here
                return true;
              });
    return person;
}

到此:

public Person myMethod() throws IOException {
    Person result = persons.stream()
              .filter(new Predicate<Person>() {
                  public boolean test(Person x) {
                      if ("test".equals(x.getName() ) ) {
                          throw new IOException("not possible inside stream y ?"); //any checked exception
                      }
                      //code here
                      return true;
                  }
              });
    return person;
}

正如您所看到的,lambda表达式中的代码现在位于匿名test类的Predicate方法内,该方法未声明任何已检查的异常。

为什么Predicate?因为它是filter方法所期望的,并且您可以使用lambda而不是传统对象,因为它是单个方法接口:只有test是抽象的,并且您的lambda签名应该是相同的作为Predicate.test方法。

如果您真的希望能够处理已检查的异常,linked post(在Frederico的评论中)显示了一些绕过这些限制的方法。

答案 1 :(得分:4)

  

寻找不被允许的原因?

您正在实施一个Predicate,它不会声明已检查的异常。

例外是副作用,没有功能设计师的青睐,很可能这就是他们得不到很好支持的原因。

我使用技巧将已检查的异常传递出去并在以后捕获它。另一个选择是使用未经检查的异常包装它或使用类似IORuntimeException的类。在不同的情况下,我使用所有三个选项。

https://vanilla-java.github.io/2016/06/21/Reviewing-Exception-Handling.html