1

Let's say there's an Optional optString. Now if I use it as below:

optString.ifPresent({
    //some statements
    }, () -> throw new Exception());`, it fails to compile.

Why do I've to wrap the throw new Exception() inside curly braces {}.

Why can't I simply do () -> throw new Exception.

Why is the compiler treating throw and new as some states that should be in a block?

In IntelliJ it fails with compilation errors: expected ) expected { expected; and Unexpected token

A complete example:

class OptionalTest {

    Optional<String> testString() {
        return Optional.empty();
    }
    
    void getString() {
        var optStr = testString();
        optStr.ifPresentOrElse(s -> {
            
        }, () -> throw new RuntimeException());
    }
}
Mark Rotteveel
  • 100,966
  • 191
  • 140
  • 197
Mohammad
  • 187
  • 1
  • 12

1 Answers1

1

You cannot simply throw in the lambda expression the way you did since a lambda body is either a single expression or a block. The throw is a statement.

You have to wrap throwing an exception into the block:

optStr.ifPresentOrElse(
    str -> /*do something*/,
    () -> { throw new RuntimeException(); });

It is also worth mentioning Optional#orElseThrow which is designed to actually throw an exception. The only argument passed into the Supplier is the way to instantiate the exception, the method just takes it and throws instead of you if the Optional is empty.

optStr.orElseThrow(() -> new RuntimeException());
Nikolas Charalambidis
  • 40,893
  • 16
  • 117
  • 183
  • So what is the equivalent of `optStr.ifPresent( /*do something*/).orElseThrow();` – Mohammad Oct 27 '21 at 10:41
  • @Mohammad Ah, I get your question. I have edited my answer accordingly. – Nikolas Charalambidis Oct 27 '21 at 10:50
  • 1
    Side note: when the Java designers worked on the new `switch` syntax, they considered it too annoying to wrap `throw` statements in braces, so they added a syntactic exception, so you can write, e.g. `switch(someString) { case null -> throw new RuntimeException("is null"); case String s -> /* do something with s */ System.out.println(s); }`. But I don’t know of any plans to allow the same for lambda expressions. – Holger Oct 27 '21 at 12:46
  • @Holger: Do you have any sources? I would like to read more about it. – Nikolas Charalambidis Oct 27 '21 at 15:50
  • 1
    The syntax is in [the language specification](https://docs.oracle.com/javase/specs/jls/se17/html/jls-14.html#jls-14.11.1); as you can see, there are the alternatives `SwitchRule: SwitchLabel -> Expression ; SwitchLabel -> Block SwitchLabel -> ThrowStatement`. My example used even newer syntax which JDK 17 only provides as [preview feature](https://docs.oracle.com/javase/specs/jls/se17/preview/specs/patterns-switch-jls.html#jls-14.11). – Holger Oct 27 '21 at 17:59