Request for review: proposal for @FunctionalInterface checking

Stephen Colebourne scolebourne at joda.org
Wed Jan 2 15:21:41 PST 2013


Putting my user hat on and imagining writing framework-type code using
functional interfaces, I think that the annotation is a good idea.
However, encoding the signature seems a little unnecessary when
standard Java reflection of the SAM method gets you that information.

The problem is finding that SAM method to perform reflection on. A
simple loop of all methods to find the only non-default one isn't
enough. You'll also have to filter methods on Object and handle
multiple superclass hierarchies. Basically, implement the full JLS
search. Very non-ideal.

In an ideal world, what I want is this:

@FunctionalInterface(method=Predicate#test)
interface Predicate<T> { ... }

where Predicate#test is a reference returning a reflection Method
object (as that can be introspected further, but Predicate::test
cannot). This approach would also deal with interface hierarchies (so
that the sub-interface can specify which super-interface it intends to
have provide the SAM).

The next best would seem to be:

@FunctionalInterface(samClass=Predicate.class, samMethod="test")
interface Predicate<T> { ... }

Specifying the signature of the SAM seems like the wrong this to be
chasing here.


As a side note, an alternative approach would be reflection helper methods:

 public static Method isFunctionalInterface(Class<?> interfce)
 public static Method findFunctionalInterfaceMethod(Class<?> interfce)

This may actually be more broadly applicable.

Stephen



On 2 January 2013 19:13, Brian Goetz <brian.goetz at oracle.com> wrote:
> In Doug's "tyranny of function names", there was an appeal for a known,
> regularized naming convention:
>
>>  Using anything other than a known regularized naming scheme
>> in libraries will make it impossible to ever take advantage of
>> language-based function type support.
>
>
> Perhaps @FunctionalInterface can be extended to provide this.  Instead of
> just
>
> @FunctionalInterface
> interface Predicate<T> { ... }
>
> the annotation could capture the parameter and return types as well:
>
> @FunctionalInterface(return = boolean.class,
>                      params = { Object.class })
> interface Predicate<T> { ... }
>
> (or better, some scheme that lets us encode generic signatures rather than
> erased ones).
>
> Then we're making a clear statement that "Predicate<T> is a functional
> interface with type signature T->boolean", which would open the door to
> future loosenings in a less ad-hoc way?
>
> Doug, does this help at all?
>
>
> On 12/28/2012 3:02 PM, Joe Darcy wrote:
>>
>> Hello,
>>
>> We've had some discussions internally at Oracle about adding a
>> FunctionalInterface annotation type to the platform and we'd now like to
>> get the expert group's evaluation and feedback on the proposal.
>>
>> Just as the java.lang.Override annotation type allows compile-time
>> checking of programmer intent to override a method, the goal for the
>> FunctionalInterface annotation type is to enable analogous compile-time
>> checking of whether or not an interface type is functional.  Draft
>> specification:
>>
>> package java.lang;
>>
>> /**
>> Indicates that an interface type declaration is intended to be a
>> <i>functional interface</i> as defined by the Java Language
>> Specification.  Conceptually, a functional interface has exactly one
>> abstract method.  Since default methods are not abstract, any default
>> methods declared in an interface do not contribute to its abstract
>> method count.  If an interface declares a method overriding one of the
>> public methods of java.lang.Object, that also does <em>not</em> count
>> toward the abstract method count.
>>
>> Note that instances of functional interfaces can be created with lambda
>> expressions, method references, or constructor references.
>>
>> If a type is annotated with this annotation type, compilers are required
>> to generate an error message unless:
>>
>> <ul>
>> <li> The type is an interface type and not an annotation type, enum, or
>> class.
>> <li> The annotated type satisfies the requirements of a functional
>> interface.
>> </ul>
>>
>> @jls 9.8 Functional Interfaces
>> @jls 9.4.3 Interface Method Body
>> @jls 9.6.3.8 FunctionalInterface  [Interfaces in the java.lang package
>> get a corresponding JLS section]
>> @since 1.8
>> */
>> @Documented
>> @Retention(RUNTIME)
>> @Target(TYPE)
>> @interface FunctionalInterface {} // Marker annotation
>>
>> Annotations on interfaces are *not* inherited, which is the proper
>> semantics in this case.  A subinterface of a functional interface can
>> add methods and thus not itself be functional.  There are some
>> subtleties to the definition of a functional interface, but I thought
>> that including those by reference to the JLS was sufficient and putting
>> in all the details would be more likely to confuse than clarify.
>>
>> Please send comments by January 4, 2013; thanks,
>>
>> -Joe
>>
>


More information about the lambda-spec-comments mailing list