As Brian Goetz pointed out in a comment, the basis for the design decision was to allow adapting a method to a functional interface the same way you can call the method, i.e. you can call every value returning method and ignore the returned value.
When it comes to lambda expressions, things get a bit more complicated. There are two forms of lambda expressions, (args) -> expression
and (args) -> { statements* }
.
Whether the second form is void
compatible, depends on the question whether no code path attempts to return a value, e.g. () -> { return ""; }
is not void
compatible, but expression compatible, whereas () -> {}
or () -> { return; }
are void
compatible. Note that () -> { for(;;); }
and () -> { throw new RuntimeException(); }
are both, void
compatible and value compatible, as they don’t complete normally and there’s no return
statement.
The form (arg) -> expression
is value compatible if the expression evaluates to a value. But there are also expressions, which are statements at the same time. These expressions may have a side effect and therefore can be written as stand-alone statement for producing the side effect only, ignoring the produced result. Similarly, the form (arg) -> expression
can be void
compatible, if the expression is also a statement.
An expression of the form s -> s
can’t be void
compatible as s
is not a statement, i.e. you can’t write s -> { s; }
either. On the other hand s -> s.toString()
can be void
compatible, because method invocations are statements. Similarly, s -> i++
can be void
compatible as increments can be used as a statement, so s -> { i++; }
is valid too. Of course, i
has to be a field for this to work, not a local variable.
The Java Language Specification §14.8. Expression Statements lists all expressions which may be used as statements. Besides the already mentioned method invocations and increment/?decrement operators, it names assignments and class instance creation expressions, so s -> foo=s
and s -> new WhatEver(s)
are void
compatible too.
As a side note, the form (arg) -> methodReturningVoid(arg)
is the only expression form that is not value compatible.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…