I have a use case where it would be useful to use reflection to get the parameter and return value types of Function objects1.
But I discovered to following surprising behaviour of function objects resulting from lambda expressions: The object don't have an apply method with specific types.
Example code:
import java.lang.reflect.Type;
import java.lang.reflect.Method;
import java.util.function.Function;
public class Trying {
    public static void main(String[] args) {
        Function<Integer, Double> lambda = i -> i.doubleValue();
        Function<Integer, Double> methodRef = Integer::doubleValue;
        Function<Integer, Double> anon = new Function<Integer, Double>() {
            @Override
            public Double apply(Integer i) {
                return i.doubleValue();
            }
        };
        printType("lambda", lambda);
        printType("methodRef", methodRef);
        printType("anon", anon);
    }
    private static void printType(String name, Function<?, ?> f) {
        System.out.println("### " + name);
        System.out.println("super: " + f.getClass().getSuperclass().getSimpleName());
        for (Type i : f.getClass().getGenericInterfaces()) {
            System.out.println("interface: " + i);
        }
        for (Method m : f.getClass().getDeclaredMethods()) {
            System.out.println("name: " + m.getName() + ", bridge: " + m.isBridge()
                + ", arg type: " + m.getParameterTypes()[0].getSimpleName()
                + ", return type: " + m.getReturnType().getSimpleName());
        }
        System.out.println();
    }
}
This code prints the following:
### methodRef
super: Object
interface: interface java.util.function.Function
name: apply, bridge: false, arg type: Object, return type: Object
### lambda
super: Object
interface: interface java.util.function.Function
name: apply, bridge: false, arg type: Object, return type: Object
### anon
super: Object
interface: java.util.function.Function<java.lang.Integer, java.lang.Double>
name: apply, bridge: false, arg type: Integer, return type: Double
name: apply, bridge: true, arg type: Object, return type: Object
- Is there some way to work around this issue and use reflection to get the concrete types of the function objects?
 - Is the the language specified behaviour, or implementation dependent?
 - Why do the lambda and method reference objects behave in this way?
 
1: I want to use this information to create default converters for a databinding API.