Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java lambda only throwing expression-style instead of statement-style [duplicate]

In Java (using Java 8 currently), I can write this and all will compile nice and well:

Supplier<Long> asd = () -> {
    throw new RuntimeException();
};

Yet, I cannot write this:

Supplier<Long> asd = () -> throw new RuntimeException(); // This won't compile :(

Does anyone know why Java's implementation does not allow such style (expression lambda) and only the statement/code-block style lambda?

I mean, since the lambda is only throwing the RuntimeException, why isn't the JDK able to infer the lambda expression as:

new Supplier<Long>() {
    @Override
    public Long get() {
        throw new RuntimeException();
    }
};

Is this documented somewhere in the specs/docs? Is this added only in JDK > 8?

like image 480
Tamir Nauman Avatar asked Nov 30 '18 12:11

Tamir Nauman


2 Answers

From the language spec JLS 15.27.2:

A lambda body is either a single expression or a block (§14.2). 

throw is not a single expression (it's a statement); so you have to use it in a block.

like image 176
Andy Turner Avatar answered Oct 20 '22 09:10

Andy Turner


What you wrote is an invalid lambda. There is a difference between the expression with the brackets {} and without. See the example. The following means that 1L is returned.

Supplier<Long> asd = () -> 1L;

which is equivalent to:

Supplier<Long> asd = () -> {
    return 1L;
}; 

However, when you write:

Supplier<Long> asd = () -> throw new RuntimeException();

It would be translated following which is an invalid lambda:

Supplier<Long> asd = () -> {
     return throw new RuntimeException();                    // invalid expression in Java
};

In a nutshell, you can understand () -> 1L as a shortcut for { return 1L; }.

like image 34
Nikolas Charalambidis Avatar answered Oct 20 '22 09:10

Nikolas Charalambidis