Java MethodHandles可以被认为与第一类函数相同吗?

Luc*_*ano 9 java higher-order-functions java-7

Java 方法类和Java 7的MethodHandle类都引用与方法关联的对象,但它们很少使用,当函数需要传递给另一个时,最好使用实现包含一个的接口的匿名类方法.

(注意:MethodHandles应该比旧方法更快.)

为什么这些结构不经常用于将函数传递给函数?是因为它们仍然冗长吗?

代码示例:

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));
}
}
Run Code Online (Sandbox Code Playgroud)

UPDATE

在做了一些基准测试之后,我注意到MethodHandle比Reflection的方法更快,但仍远不及常规方法调用.也许对于方法调用,JVM可以应用一些句柄无法实现的优化.

Dan*_*ton 3

除了任何性能参数之外,传递方法或方法句柄:

  • 失去任何编译时安全性:
    • 参数数量;
    • 参数类型;
    • 方法本身的存在(您使用字符串名称来查找它)。
  • 丢失任何已声明的已检查异常;
  • 使自动化重构变得更加困难。

此外,正如您的代码所示,使用Methods或MethodHandles并不会特别减少声明近似第一类函数的对象所需的代码量:

// 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);
    }
}
Run Code Online (Sandbox Code Playgroud)

诚然,它不如真正的 lambda 语法那么好,但类型安全、重构的好处和易于解释使得键入这五行在大多数情况下是最不糟糕的选择。