在 java 中传递和执行成员函数
passing and enforcing a member function in java
我正在尝试创建一个工作队列 class (FooQueue),其中包含:
- 一组正在工作的函数成员 (do*)。他们每个人都有一个参数,具有相同的类型(FooItem)。
- 一个 'add' 函数,它有两个参数:上述函数之一和一个 FooItem。最重要的是,add 函数应该只能接受 FooQueue class 的成员函数,而不是另一个具有相似签名
的 class 的成员函数
代码在 do 函数为静态时编译,但在函数为非静态时不编译,即使根据 this 实例函数成员的定义是正确的。
应该更改什么才能使其成为 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" );
}
}
它与静态/非静态方法无关,也与泛型无关,仅与 BiConsumer
定义有关。
BiConsumer
需要两个参数,因此您需要需要两个参数并且 return 不需要任何参数的 lambda。
要解决这个问题,请使用 实例方法参考:
FooQueue q = new FooQueue();
q.add(FooQueue::do1, new FooItem());
不要将它与静态方法引用混淆。 FooQueue::do1
是 lambda 的语法糖:
(qInstance, item) -> qInstance.do1(item));
这种方法只允许您接受来自 FooQueue
的方法。
请注意,q:do1
与 BiConsumer
不兼容,因为它已转换为:
(item) -> q.do1(item)
阅读更多关于 Instance method reference
具有不同 类
的完整示例
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 {
}
我正在尝试创建一个工作队列 class (FooQueue),其中包含:
- 一组正在工作的函数成员 (do*)。他们每个人都有一个参数,具有相同的类型(FooItem)。
- 一个 'add' 函数,它有两个参数:上述函数之一和一个 FooItem。最重要的是,add 函数应该只能接受 FooQueue class 的成员函数,而不是另一个具有相似签名 的 class 的成员函数
代码在 do 函数为静态时编译,但在函数为非静态时不编译,即使根据 this 实例函数成员的定义是正确的。
应该更改什么才能使其成为 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" );
}
}
它与静态/非静态方法无关,也与泛型无关,仅与 BiConsumer
定义有关。
BiConsumer
需要两个参数,因此您需要需要两个参数并且 return 不需要任何参数的 lambda。
要解决这个问题,请使用 实例方法参考:
FooQueue q = new FooQueue();
q.add(FooQueue::do1, new FooItem());
不要将它与静态方法引用混淆。 FooQueue::do1
是 lambda 的语法糖:
(qInstance, item) -> qInstance.do1(item));
这种方法只允许您接受来自 FooQueue
的方法。
请注意,q:do1
与 BiConsumer
不兼容,因为它已转换为:
(item) -> q.do1(item)
阅读更多关于 Instance method reference
具有不同 类
的完整示例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 {
}