Limits of static method references in Java 8

ぃ、小莉子 提交于 2019-12-09 16:58:57

问题


I'm trying to use method references to capture method invocations and am hitting some limitations. This works fine:

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

private interface Foo {
  String getBar();
} 

capture(Foo::getBar);

But if I change the signature of Foo.setBar to something like this:

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

capture(Foo::setBar);

I get an error:

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

It's not clear to me what the restriction is. Ideally I'd like to use method references to capture invocations on standard setter. Is there any way to do this?


回答1:


There are two problems here:

  • You're using Function, which has to return something. setBar doesn't return anything.
  • Function only takes a single input, but you've got two inputs: the Foo you'd call setBar on, and the String argument you'd pass into setBar.

If you change to use BiConsumer instead (which has a void return type and two inputs) it works fine:

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

You can overload your capture method to have both signatures:

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

and then use both method references:

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



回答2:


Foo::getBar corresponds to a function that takes a Foo (the target object) and returns a String. The interface Function<Foo, String> can be used to represent such a function.

On the other hand, Foo::setBar corresponds to a function that takes two arguments, a Foo (the target object) and a String (the first parameter). The matching interface is BiConsumer<Foo, String>. That means you need an overload for BiConsumer:

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



回答3:


Expose syntax sugar method reference, you should see, that

Foo::getBar

is equal to

(Foo)foo -> foo.getBar()

which is Function <Foo, String>

But

Foo::setBar

is in this context the function of two variables (foo and some String str), so it is not the function of one variable (Function)

For the more convenient answer you should see, where the method references are allowed:

  1. Reference to a static method (not this case at all)
  2. Reference to an instance method of a particular object (not this case at all)
  3. Reference to an instance method of an arbitrary object of a particular type (this case)

    In the instruction above there is an example, which is almost the same as in your case. And it is said, that the equivalent lambda expression would be taking two parameters (in this case Foo and String), which is not Function

  4. Reference to a constructor (not this case at all)



来源:https://stackoverflow.com/questions/23794186/limits-of-static-method-references-in-java-8

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!