4

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 looking for reason why it is not being allowed ? Even if method in which code is declared throws IOException

Om.
  • 2,532
  • 4
  • 22
  • 22
  • 2
    What is the error that you get? Maybe a missing return statement? I think this should be possible. – keuleJ Mar 11 '17 at 18:52
  • 1
    The lambda's gotta return a `boolean`. Other than that you are good. – sparc_spread Mar 11 '17 at 19:06
  • Sorry updated my question. I am unable to throw checked exception even if it is declared as throws in method signature or whole expression is under try/catch.... Looking for reason why ? Or if there r ways which we can do it. – Om. Mar 12 '17 at 02:20
  • 1
    Possible duplicate of [How can I throw CHECKED exceptions from inside Java 8 streams?](http://stackoverflow.com/questions/27644361/how-can-i-throw-checked-exceptions-from-inside-java-8-streams) – fps Mar 12 '17 at 03:49
  • Thanks @Federico. So its a bug – Om. Mar 12 '17 at 13:18

2 Answers2

6

your code is working perfectly, apart from a missing semi colon at the end of the throw new ... line, and from a missing a return statement that may be hidden in // code here.

What you can't do is throw a checked exception (which RuntimeException is not) because checked exception are part of the method signature and the Predicate.test method do not declare one.

EDIT : To see more precisely what is happening and why you can't throw a checked exception here, here is how you could have written the code without lambda :

From this :

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;
}

to this :

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;
}

As you can see, the code inside the lambda expression is now inside the test method of an anonymous Predicate class, which is not declaring any checked exception.

Why Predicate ? Because it is what the filter method is expecting, and you can use a lambda instead of a conventional object because it is a single method interface : only test is abstract, and your lambda signature should be the same as the Predicate.test method.

If you really wish to be able to handle checked exceptions, the linked post (in a comment from Frederico) show some ways to bypass these limitations.

Community
  • 1
  • 1
Thierry
  • 5,270
  • 33
  • 39
  • Sorry updated my question. I am unable to throw checked exception even if it is declared as throws in method signature or whole expression is under try/catch.... Looking for reason why ? Or if there r ways which we can do it. – Om. Mar 12 '17 at 02:20
  • I wouldn’t say that the lambda expression is inside the `test` method—that’s too misleading. The lambda expression is inside `myMethod`, but it has to fulfill the signature constraints of the `test` method. – Holger Mar 13 '17 at 12:18
  • @Holger : i didn't mean the lambda expression, but the code inside the lambda. I'll edit to clarify this. – Thierry Mar 13 '17 at 13:01
  • I know what you mean, but the code of the lambda expression isn’t inside the `test` method; code inside the `test` method can access inherited members of the `Predicate` interface and within the `test` method, `this` refers to the `Predicate` instance. Neither applies to the code of the lambda expression, it can’t access `Predicate` members and `this` refers to the owner of `myMethod()`. Also the accessibility rules are different. The only relationship to the `test` method is the requirement to fulfill its signature contract. – Holger Mar 13 '17 at 13:07
  • Good points about the accessibility rules. I'll edit further to remove the wrong parts – Thierry Mar 13 '17 at 14:24
5

looking for reason why it is not being allowed ?

You are implementing a Predicate which doesn't declare a checked Exception.

Exceptions are side effects and no favoured by functional designers and most likely this is the reason they are not supported very well.

I use a trick to pass the checked exception out and catch it later. Another option is to wrap it with an unchecked exception or use a class like IORuntimeException In different cases I use all three options.

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

Peter Lawrey
  • 525,659
  • 79
  • 751
  • 1,130