JDK-8015236 : Provide Class.isFuntionalInterface functionality in core reflection
  • Type: Enhancement
  • Component: core-libs
  • Sub-Component: java.lang:reflect
  • Affected Version: 8
  • Priority: P4
  • Status: Open
  • Resolution: Unresolved
  • OS: generic
  • CPU: generic
  • Submitted: 2013-05-22
  • Updated: 2015-02-03
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
Other
tbd_majorUnresolved
Related Reports
Blocks :  
Relates :  
Relates :  
Relates :  
Description
It would be helpful if core reflection included at least an approximation to a Class.isFuntionalInterface predicate.
Comments
Plan is to defer for 8, possibly take up again in the future.
20-09-2013

Since this idea was proposed, there have been some significant changes: i) the VM (and, by extension, reflection) no longer knows or cares about the language-level concept of overriding (where descriptors are different due to generics or covariant overriding); ii) the LambdaMetafactory no longer knows or cares about interfaces with a single method. As a result, there is not longer a clear-cut definition of "functional interface" for the reflection library, nor is there a definitive use case in the standard API (i.e., what can I do with this thing if isFunctionalInterface returns true?) It is reasonable that clients of the LambdaMetafactory might still want to reflectively identify a descriptor(s) to implement, and there is some non-trivial logic involved. But it's not clear exactly what the reflection API should do to help this process. Examples of alternatives: -- Alternative 1 (no API change): Class<?> c = ...; List<Method> abs = Arrays.stream(c.getMethods()) .filter(m -> Modifier.isAbstract(m.getModifiers())) .filter(m -> /* complicated logic to match object methods */) // if desired .collect(something); // excuse my ignorance of streams if (c.isInterface() && abs.length == 1) // call metafactory else // error -- Alternative 2 (no API change): Class<?> c = ...; if (c.isAnnotationPresent(FunctionalInterface.class)) { List<Method> abs = Arrays.stream(c.getMethods()) .filter(m -> Modifier.isAbstract(m.getModifiers())) .filter(m -> /* complicated logic to match object methods */) // mandatory .collect(something); // excuse my ignorance of streams // call metafactory with all methods } else // error -- Alternative 3 (isFunctionalInterface, getFunctionalInterfaceMethod): Class<?> c = ...; if (c.isFunctionalInterface()) { Method m = c.getFunctionalInterfaceMethod(); // call metafactory } else // error -- Alternative 4 (getAbstractMethods): Class<?> c = ...; if (c.isInterface()) { Method[] abs = c.getAbstractMethods(); // automatically filters interfaces' object methods if (c.isAnnotationPresent(FunctionalInterface.class)) // call metafactory with all methods (optional) else if (abs.length == 1) // call metafactory else // error } else // error -- I kind of like the general-purpose utility of the last one. If someone wants to implement a class/interface by _any_ means, they need to know its abstract methods, and so 'getAbstractMethods' would nicely fill a hole there.
19-09-2013

This method, if it exists, is likely related to the valid inputs to the LambdaMetafactory. We need to sort out the corner-case behaviors there before we know what a class-level view of "functional interface" looks like.
02-07-2013