Functional interface confusion

Remi Forax forax at
Sun Jul 7 04:25:31 PDT 2013

On 07/07/2013 11:25 AM, Stephen Colebourne wrote:
> Its certainly a pain for me in this case. I understand why its
> half-allowed (references only), but I think it has certain issues
> still.
> Firstly, IntelliJ Idea IDE editor indicated that @FunctionalInterface
> was invalid for the interface here. But the compiler did not. So there
> is an inconsistency. Given the below, it sounds like a bug in
> IntelliJ. If not, then the @FunctionalInterface Javadoc needs
> updating.
> Secondly, I would prefer that this was valid as a way to resolve the problem:
> static <T extends Temporal> TemporalAdjuster firstDayOfMonth() {
>    return (T temporal) -> (T) temporal.with(DAY_OF_MONTH, 1);
> }

Casting is never the right incantation when you have trouble with 
generics :)

  The syntax should be something like this:
    (<T extends Temporal> T temporal) -> temporal.with(DAY_OF_MONTH, 1);
otherwise the compiler doesn't know if T is declaration of a type 
parameter or
a type variable declared before.

So this syntax is not natural and chance to discover it by yourself is 
close to 0.

> Not that it is overly useful as a general construct (it doesn't solve
> my problem here), just that it would be easier to explain in a
> learning environment, and no doubt occasionally useful. I know you
> don't want to hear it, but not supporting the solution above feels
> like a bug in the spec to me, given that the whole purpose of defining
> actual types in the lambda parameter area is to express a
> non-inferable type.

but your proposed syntax relies on the fact that the compiler is able to 
if T is a declaration or just a use ?

> (To be clear, I'm happy enough to agree with the absence of special
> syntax on the lambda itself for declaring T)
> @Remi, using a method reference is appropriate for the example, but
> not in general, as end users will be using this. As such, I have no
> choice but to leave it without generics, which makes me sad.

Writing a generics method (not a lambda, just a generic method) is not 
users are used to. Framework developers are used to that, not end users.

In your case, if someone want to write a non ISO calendar, asking him/her
to use method references doesn't seem to be a big deal for me.

> Stephen


> On 7 July 2013 02:44, Brian Goetz <brian.goetz at> wrote:
>> You've pretty much figured it out.
>> There was some question as to whether to allow the single method in a SAM to
>> be a generic method or not.  There's no theoretical problem with SAMs that
>> have generic methods, and this works perfectly well with method refs: you
>> can assign a method ref for a generic method to a (compatible) SAM with a
>> generic method.  But for lambdas, there's no syntax for it; you'd need extra
>> syntax to name the type parameter.  (No, please don't suggest any; they've
>> all been considered.)  Note that there are no problems with SAMs being
>> generic classes; we're only talking about methods that themselves introduce
>> generic type parameters, like your TemporalAdjuster example.
>> In the end we decided to go the slightly odd middle ground of not
>> prohibiting SAMs with generic methods (after all, they can be used perfectly
>> well with method refs) but not inventing a syntax for generic lambdas.
>> We're pretty comfortable with this choice; it comes up rarely, and in those
>> rare cases, all you have to do is manually desugar the lambda to method, and
>> take a method ref of that.  So TemporalAdjuster is a valid SAM, but its
>> harder to use than most SAMs.  For API code, you probably do want to avoid
>> this kind of functional interface.
>> On 7/6/2013 5:39 PM, Stephen Colebourne wrote:
>>> I tried to create this interface today, and the compiler complained:
>>> @FunctionalInterface
>>> public interface TemporalAdjuster {
>>>       <T extends Temporal> T adjustInto(T temporal);
>>> }
>>> static TemporalAdjuster firstDayOfMonth() {
>>>     return (temporal) -> temporal.with(DAY_OF_MONTH, 1);
>>> }
>>> java: incompatible types: invalid functional descriptor for lambda
>>> expression
>>>       method <T>(T)T in interface java.time.temporal.TemporalAdjuster is
>>> generic
>>> The same error was seen with this:
>>> static <T extends Temporal> TemporalAdjuster firstDayOfMonth() {
>>>     return (T temporal) -> (T) temporal.with(DAY_OF_MONTH, 1);
>>> }
>>> I must admit that I wasn't expecting this, as nothing in the
>>> documentation of @FunctionalInterface or other recent discussions that
>>> I have seen indicated to me that there is a limitation on lambdas and
>>> method-based generics. (FYI, method-based generics are correct here.
>>> Generifying the interface TemporalAdjuster would not represent the
>>> same logical thing in the codebase. The only constraint is on the
>>> method.)
>>> By contrast, this seems to work fine:
>>> @FunctionalInterface
>>> public interface TemporalQuery<R> {
>>>       R queryFrom(TemporalAccessor temporal);
>>> }
>>> static final TemporalQuery<ZoneId> ZONE_ID = (temporal) -> {
>>>     return temporal.query(ZONE_ID);
>>> };
>>> Is the compiler wrong? Is the spec of FunctionalInterface incomplete
>>> (perhaps deliberately)?
>>> (compiler I'm using is old and on the
>>> branch)
>>> I think I understand why the first example cannot be a lambda, as
>>> there is no way to grab the <T> in the lambda body, but I'd like a
>>> proper explanation! It definitely feels like an awkward edge case, and
>>> I suspect I'll be forced back to the ungenerified version.
>>> thanks
>>> Stephen

More information about the lambda-dev mailing list