Java Method Class and Java 7's MethodHandle Class both refer to objects that are associated to methods, but still they are rarely used and when a function needs to be passed to another, it is preferred to use an anonymous class that implements an interface that contains one method.
(Note: MethodHandles are supposed to be faster than the old Methods.)
Why aren't these constructs used more often to pass functions to functions? Is it because they are still verbose?
Code example:
public final class HigherOrder {
public static final List<?> map(final List<?> list, final MethodHandle mh) throws Throwable {
if (list == null) return null;
List<Object> ret = new ArrayList<>(list.size());
for (Object element : list) {
ret.add(mh.invoke(element));
}
return ret;
}
public static final Object reduce(final List<?> list, final MethodHandle mh) throws Throwable {
if (list == null) return null;
Object tmp = list.get(0);
for (int i = 1; i < list.size(); i++) {
tmp = mh.invoke(tmp, list.get(i));
}
return tmp;
}
public static final Integer doubleNumber(final Integer number) {
return number * 2;
}
public static final Integer sum(final Integer number1, final Integer number2) {
return number1 + number2;
}
public static void main(String[] args) throws Throwable {
MethodHandles.Lookup lookup = MethodHandles.lookup();
MethodHandle doubleNumber = lookup.unreflect(HigherOrder.class.getMethod("doubleNumber", Integer.class));
MethodHandle sum = lookup.findStatic(HigherOrder.class, "sum", MethodType.methodType(Integer.class, Integer.class, Integer.class));
List<?> list = Arrays.asList(1, 2, 3, 4, 5);
System.out.println(list);
list = map(list, doubleNumber);
System.out.println(list);
System.out.println(reduce(list, sum));
}
}
UPDATE
After doing some benchmarking, I noticed that MethodHandle is faster than Reflection's method, but still nowhere near as fast as a regular method call. Maybe for the method call the JVM can apply some optimizations that are not possible with the handles.
Aside from any performance arguments, passing around Methods or MethodHandles:
Also, as your code demonstrates, using Methods or MethodHandles doesn't particularly cut down on the amount of code required to declare an object approximating a first-class function:
// you could even use the Function types from Guava...
interface Func<In, Out> {
Out apply(In in);
}
// create a new "function" object in 5 lines of code:
Func<String, Integer> parseInt = new Func<String, Integer> {
public Integer apply(String in) {
return Integer.parseInt(in);
}
}
Admittedly it's not as nice as a real lambda syntax, but the type-safety, refactoring benefits and ease of explanation make typing out those five lines the least-worst option much of the time.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With