I'm trying to create a work queue class (FooQueue) that has:
The code compiles when the do function is static, but not when the function is non-static, even though acording to this the definition of the instance function member is correct.
What should be changed to make it compile/run?
public class App {
public static void main( String[] args ) {
FooQueue q = new FooQueue();
q.add( FooQueue::dos, new FooItem() ); // this compiles
q.add( q::do1, new FooItem() ); // this does not:
// does not consider q::do1 'delegate'
// as taking 2 parameters,
// with q being the first one
FooQueue q2 = new FooQueue2();
q.add( FooQueue2::dos, new FooItem() ); // want this to give compiler error
q.add( FooQueue2::do1, new FooItem() ); // want this to give compiler error
}
}
public class FooQueue {
public static void dos( FooQueue q, FooItem item ) {
System.out.println( "FooQueue:sdo" );
}
public void do1( FooItem item ) {
System.out.println( "FooQueue:do1" );
}
public void add( java.util.function.BiConsumer<FooQueue,FooItem> func, FooItem wi ) {
System.out.println( "FooQueue:addWorkItem2" );
func.accept( this, wi );
}
}
public class FooItem {
}
public class FooQueue2 {
public static void dos( FooQueue2 q2, FooItem item ) {
System.out.println( "FooQueue2:sdo" );
}
public void do1( FooItem item ) {
System.out.println( "FooQueue2:do1" );
}
}
It's not related to static / non-static method, nor generics, but only to BiConsumer
definition.
BiConsumer
requires two parameters, so you need lambda that requires two parameters and doesn't return any.
To fix that, use instance method reference:
FooQueue q = new FooQueue();
q.add(FooQueue::do1, new FooItem());
Don't confuse it with static method reference. FooQueue::do1
is syntatic sugar for lambda:
(qInstance, item) -> qInstance.do1(item));
This approach allows you to accept only methods from FooQueue
.
Note that q:do1
is not compatible with BiConsumer
as it's converted to:
(item) -> q.do1(item)
Read more about Instance method reference
Full example with different classes
public class App {
public static void main(String[] args) {
FooQueue q = new FooQueue();
FooQueue2 q2 = new FooQueue2();
q.add(FooQueue::do1, new FooItem());
// Equals to:
q.add((qInstance, item) -> qInstance.do1(item), new FooItem());
// q.add(FooQueue2::do1, new FooItem()); // not compile
}
}
class FooQueue {
void do1(FooItem item) {
System.out.println("FooQueue:do1");
}
void add(BiConsumer<FooQueue, FooItem> func, FooItem wi) {
System.out.println("FooQueue:addWorkItem");
func.accept(this, wi);
}
}
// class that pretends to be FooQueue
class FooQueue2 {
void do1(FooItem item) {
System.out.println("FooQueue2:do1");
}
}
class FooItem {
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With