【问题标题】:How to indirectly run a method reference in Java 8?如何在 Java 8 中间接运行方法引用?
【发布时间】:2013-06-18 07:40:10
【问题描述】:

一般问题是:

  • 在使用object::aMethod语法时,是否可以转换为MethodHandle等类型作为功能接口?
  • 如果不是,如果可能的话,如何在 Java 8 中间接调用方法引用?

举个例子,假设我们想要一个MethodRefRunner

class MethodRefRunner {
  static void execute(Object target, WHATTYPE mref, Object... args) {
    mref.apply(args);
  }
}

它可以用作:MethodRefRunner.execute(o, o::someMethod, someParam)

在上面的 sn-p 中,WHATTYPE 的一个选项是java.util.function.Function,但非常严格。正如this answer 提到的,在b75 版本之前,有一个java.util.function.Block 可用并且可能很方便。

另一方面,WHATTYPE 是否有可能以某种方式转换为java.lang.invoke.MethodHandle

注意 Java 专家:请根据需要细化问题的标题。

【问题讨论】:

  • 在Scala中,你可以将一个方法强制转换成一个函数值,这就是eta扩展(有Scala 中 methodfunction 之间的区别)。至于您描述的情况,Scala 编译器足够聪明,可以同时接受这两种情况。
  • @Beryllium 确实有很好的对比,这也是为什么我想知道 Java 8 没有选择它的原因。
  • @nobeh Java 8 坚持使用函数式接口,因为添加函数类型会涉及到对语言的更大更改。他们可能会晚点来。
  • @nobeh 这太糟糕了。他们应该重新考虑在下次更新中添加功能类型

标签: java lambda java-8


【解决方案1】:

我认为没有任何方法可以做你想做的事。 WHATTYPE 必须是一个函数式接口——不一定是Function,而是一个单一抽象方法匹配somemethod 的接口。它是一种普通的接口类型,受管理 Java 类型的常用规则的约束。 java.util.function.Block 是一个像这样的普通接口类型,并不像你想象的那样特别。 (顺便说一句,它还在,现在称为Consumer。)

【讨论】:

  • 感谢您的回答。现在,问题是有什么方法可以在运行时将方法引用(或 lambda 表达式)转换为 MethodHandle 以便可以调用它?
  • 对不起,我认为答案仍然是否定的。原因(AFAIK)是任何这样做的方式都必须以特定 lambda 实现的形式具有固定的起点。但其目的不是限制实现——运行时可以选择“动态旋转的内部类、方法句柄周围的包装类、动态代理、方法句柄代理或其他未知机制”。 (mail.openjdk.java.net/pipermail/lambda-dev/2011-November/…)。因此,如果实际上有某种方式可以做您想做的事,那么它总是依赖于虚拟机。
  • 我发现了一个 2012 年 11 月的讨论主题,但不清楚这是否存在于任何地方:mail.openjdk.java.net/pipermail/lambda-spec-experts/…
【解决方案2】:

方法引用的工作方式与 lambda 类似,并且与 lambda 一样,它本身没有“类型”。它的类型取决于使用它的上下文。所以你的问题真的没有意义。如果您在调用此MethodRefRunner.execute() 方法时使用方法引用,那么方法引用的类型WHATTYPE 的一个实例(不管是什么),因为这就是方法的本来面目宣布接受。如果你从其他地方得到它,那么那个地方会知道它是什么类型的。

【讨论】:

  • 他的问题很有道理
猜你喜欢
  • 2019-02-25
  • 1970-01-01
  • 2018-03-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多