Java 8中静态方法引用的限制

时间:2014-05-21 21:32:18

标签: java java-8 method-reference

我正在尝试使用方法引用来捕获方法调用,并且遇到了一些限制。这很好用:

<T> void capture(Function<T, ?> in) {
}

private interface Foo {
  String getBar();
} 

capture(Foo::getBar);

但是,如果我将Foo.setBar的签名更改为:

private interface Foo {
  void setBar(String bar);
}

capture(Foo::setBar);

我收到错误:

Cannot make a static reference to the non-static method setBar(String) from the type MyTest.Foo

我不清楚限制是什么。理想情况下,我想使用方法引用来捕获标准setter上的调用。有没有办法做到这一点?

3 个答案:

答案 0 :(得分:13)

这里有两个问题:

  • 你正在使用Function,它必须返回一些东西。 setBar不会返回任何内容。
  • Function只需输入一个,但您有两个输入:Foo您要调用setBarString 1}}你要传递给setBar的论据。

如果您更改为使用BiConsumer(具有void返回类型和两个输入),则可以正常使用:

static <T, U> void capture(BiConsumer<T, U> in) {
}

您可以重载capture方法以同时拥有两个签名:

static <T, U> void capture(BiConsumer<T, U> in) { }
static <T> void capture(Function<T, ?> in) { }

然后使用两个方法引用:

capture(Foo::setBar);
capture(Foo::getBar);

答案 1 :(得分:8)

Foo::getBar对应于一个带Foo(目标对象)并返回String的函数。接口Function<Foo, String>可用于表示此类函数。

另一方面,Foo::setBar对应于一个带有两个参数的函数,Foo(目标对象)和String(第一个参数)。匹配的界面是BiConsumer<Foo, String>。这意味着您需要BiConsumer的重载:

<T, U> void capture(BiConsumer<T, U> setter) {
    // ...
}

答案 2 :(得分:3)

暴露语法糖方法参考,您应该看到,

Foo::getBar

等于

(Foo)foo -> foo.getBar()

Function <Foo, String>

但是

Foo::setBar

在这个上下文中是两个变量(foo和一些String str)的函数,因此它不是一个变量的函数(Function

您应该看到更方便的答案,允许method references的位置:

  1. 引用静态方法(完全不是这种情况)
  2. 引用特定对象的实例方法(完全不是这种情况)
  3. 引用特定类型的任意对象的实例方法(本例)

    在上面的说明中有一个例子,几乎与你的情况相同。据说,等效的lambda表达式将采用两个参数(在本例中为FooString),这不是Function

  4. 对构造函数的引用(完全不是这种情况)