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.