Request for review: proposal for @FunctionalInterface checking
Joe Darcy
joe.darcy at oracle.com
Fri Dec 28 14:14:51 PST 2012
On 12/28/2012 12:30 PM, Kevin Bourrillion wrote:
> I see one important difference from @Override. @Override catches
> errors that might otherwise go completely uncaught. With a type
> intended to be a functional interface, the moment anyone ever tries to
> use it as such, there's your compilation error.
The formal definition of a functional interface from the draft JLS text is:
> More precisely, for interface I, let M be the set of abstract methods
> that are members of I but that do not have the same signature as any
> public instance method of the class Object. Then I is a functional
> interface if there exists a method m in M for which the following
> conditions hold:
>
> The signature of m is a subsignature (8.4.2) of every method's
> signature in M.
> m is return-type-substitutable (8.4.5) for every method in M.
which defines both "Z" types below as functional interfaces:
interface X { Iterable m(Iterable<String> arg); }
interface Y { Iterable<String> m(Iterable arg); }
interface Z extends X, Y {} // Functional: Y.m is a subsignature &
return-type-substitutable
interface X { <T> T execute(Action<T> a); }
interface Y { <S> S execute(Action<S> a); }
interface Exec extends X, Y {} // Functional: signatures are "the same"
I think especially the first of these examples is not immediately
obvious and would benefit from an annotation to indicate the intention
of the type, if it has such an intention.
>
> So I don't see what sets @FunctionalInterface apart from the whole
> host of static-analysis annotations that we've relegated to the
> now-abandoned JSR 305.
One difference is that lambdas are a new-to-Java language construct
being retrofitting over existing usage patterns and the proposed
annotation type is directly related to the new language feature, unlike
the JSR 305 annotation types.
Cheers,
-Joe
>
>
> On Fri, Dec 28, 2012 at 12:17 PM, Brian Goetz <brian.goetz at oracle.com
> <mailto:brian.goetz at oracle.com>> wrote:
>
> Yes. If you mark an interface as functional, and it is not, the
> compiler will warn/error. This prevents action-at-a-distance
> errors where you have a SAM, other code depends on its SAM-ness,
> and someone later decides to add another abstract method (or a
> method to one of its supertypes). It also provide extra
> documentation value.
>
> Basically, just like @Override.
>
>
> On 12/28/2012 3:16 PM, Sam Pullara wrote:
>
> Is the intent that an interface that is not functional but
> marked as such won't compile?
>
> Sam
>
> On Dec 28, 2012, at 3:12 PM, Brian Goetz
> <brian.goetz at oracle.com <mailto:brian.goetz at oracle.com>> wrote:
>
> Note that this proposal does NOT intend to change the rule
> that functional interfaces are recognized structurally;
> single-method interfaces will still be recognized as SAMs.
> This is more like @Override, where the user can
> optionally capture design intent and the compiler can warn
> when said design intent is violated.
>
> I support this proposal.
>
> 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
>
>
>
>
>
> --
> Kevin Bourrillion | Java Librarian | Google, Inc. |kevinb at google.com
> <mailto:kevinb at google.com>
More information about the lambda-libs-spec-observers
mailing list