Static Method Reference Limitations in Java 8

I am trying to use method references to call capture labels and push some restrictions. This works great:

<T> void capture(Function<T, ?> in) { } private interface Foo { String getBar(); } capture(Foo::getBar); 

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

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

I get an error message:

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

I don’t understand what such a restriction is. Ideally, I would like to use method references to capture references to a standard setter. Is there any way to do this?

+7
java java-8 method-reference
source share
3 answers

There are two problems here:

  • You are using Function , which should return something. setBar nothing.
  • Function accepts only one input, but you have two inputs: Foo you call setBar on and the String argument, which you pass to setBar .

If you use BiConsumer (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); 
+12
source share

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

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

 <T, U> void capture(BiConsumer<T, U> setter) { // ... } 
+8
source share

To expose a link to the sugar syntax method, you should see that

 Foo::getBar 

equally

 (Foo)foo -> foo.getBar() 

which is equal to Function <Foo, String>

But

 Foo::setBar 

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

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

  • Link to the static method (not in this case at all)
  • A reference to the instance method of a specific object (not in this case at all)
  • A reference to an instance method of an arbitrary object of a certain type (in this case)

    There is an example in the above instruction that is almost the same as in your case. And it is said that the equivalent lambda expression will take two parameters (in this case foo and String ), which is not Function

  • Link to the constructor (not in this case at all)

+3
source share

All Articles