Function.identity returns different type?

Paul Govereau paul.govereau at oracle.com
Wed Feb 26 10:59:28 PST 2014


Looking at this example, it seems that because the argument type of apply is
T, and the return type of asIf is T, then type inference should know that we
wanted Function.identity() to have type Function<T,T>. However, this is not
how type inference works. Type inference will not propagate typing
constraints across the invocation of apply. Technically, this is because
apply is not a "poly expression" as described in Section 15.12 of the Java
Language Specification. (Note that apply itself is not a generic method, and
in this case it does not appear in an assignment or invocation context.)

It may be easier to understand this example if we write it in a slightly
different way. Consider:

     static <T> T asIf(T t) {
         Function<T,T> f = Function.<T>identity();
         return f.apply(t);
     }

This version works perfectly well. However, if we consider what information
is available to Function.identity from type inference, the code would be more
like:

     static <T> T asIf(T t) {
         Function f = Function.identity();
         return f.apply(t);
     }

This version is clearly not correct because f has the "raw type" Function,
which is not compatible with its use in f.apply.

As suggested, a simple fix is to provide the type argument to
Function.identity like so:

     static <T> T asIf(T t) { return Function.<T>identity().apply(t); }

This tells the compiler that we would like Function.identity to return the
type Function<T,T>.

To answer your other question, asIn is OK because type information from the
return statement and the parameter list for asGiven will be combined to
provide the needed type information to Function.identity.

I hope this helps.
Paul

On 02/26/2014 12:58 PM, Samuel Dennis Borlongan wrote:
> If my experience with mucking around with generics is right, then inlining
> asGiven should be coded as :
>
>    static <T> T asIf(T t) {    return Function.<T>identity().apply(t);  }
>
> Since asGiven implicitly "supplies" the type parameter for
> Function::identity, while asIf as written does not.
>
> (Help?)
>
> Samuel Dennis R. Borlongan
>
>
> On Wed, Feb 26, 2014 at 6:14 PM, Timo Kinnunen <timo.kinnunen at gmail.com>wrote:
>
>> Hi,
>>
>>
>>
>>
>> What's the deal here, how come the "asIf" version - same as "asIn" except
>> the method "asGiven" inlined away - doesn't compile?
>>
>>
>>
>>
>>    static <T> T asIn(T t) {    return asGiven(Function.identity(), t);  }
>>
>>    static <T> T asIf(T t) {    return Function.identity().apply(t);  }
>>
>>    static <S, T> T asGiven(Function<S, T> given, S s) {    return
>> given.apply(s);  }
>>
>>
>>
>>
>> The compile error I get is:
>>
>> error: incompatible types: Object cannot be converted to T
>>
>>
>>
>>
>> But there's no mention Object in the code...
>>
>>
>>
>>
>>
>> --
>> Have a nice day,
>> Timo.
>>
>> Sent from Windows Mail
>>
>>
>


More information about the lambda-dev mailing list