Java 如何将实例方法引用定义为参数/参数

Java 如何将实例方法引用定义为参数/参数,java,lambda,arguments,parameter-passing,method-reference,Java,Lambda,Arguments,Parameter Passing,Method Reference,假设一个Person对象通过调用bookAppointment方法,请求一个Scheduler对象预订约会。但是现在没有预约。稍后,当一个约会打开时,一个约会将被预订–然后人对象想要得到通知。为了得到通知,我们需要一个特定的方法appointmentHasBeenBooked作为回调调用 为了简单起见,假设我们没有要传递的参数,并且在Person上没有为这个appointmenthasbooked方法返回值 public class Person { // Callback - To

假设一个
Person
对象通过调用
bookAppointment
方法,请求一个
Scheduler
对象预订约会。但是现在没有预约。稍后,当一个约会打开时,一个约会将被预订–然后
对象想要得到通知。为了得到通知,我们需要一个特定的方法
appointmentHasBeenBooked
作为回调调用

为了简单起见,假设我们没有要传递的参数,并且在
Person
上没有为这个
appointmenthasbooked
方法返回值

public class Person { 

    // Callback - To be invoked after the `Scheduler` object succeeds in booking an appointment. 
    public void appointmentHasBeenBooked() {
        …
    }

}
Person
类上方法
fooBar
的代码中,我们建立了一个
Scheduler
对象。理想情况下,我将能够为来自该方法的回调传递一个简单的方法引用。下面是我如何想象
foorBar
方法,当它通过
this::appointmenthasbooked
方法引用时

public class Person { 

    public void fooBar() {
        Scheduler scheduler = … ;
        scheduler.bookAppointment( this.id , this:: appointmentHasBeenBooked ) ;  // Asking the scheduler to eventually book an appointment for this person, and when accomplished, notify this person by invoking the passed method.
        …
    }

    // Callback - To be invoked after the `Scheduler` object succeeds in booking an appointment. 
    public void appointmentHasBeenBooked() {
        …
    }

}
这可能吗?我还没有定义一个接口,更不用说定义一个

➥ 如果这是可能的,我如何定义
Scheduler
method
bookhasbeenappoint
上的参数/参数作为方法引用

接收方法引用的方法如何调用该方法

public class Scheduler {
    public void bookAppointment( UUID id , methRef ) {
        … book the appointment
        invoke_methRef ;
    }
}
在上面的代码中,我要说明什么:

  • methRef
  • invoke\u methRef
我看到了许多传递方法引用的示例,例如
this::toString
。但是我没有看到任何关于定义传递的方法引用的接收端的解释

我知道实现我的目标的更为漫长的迂回的方法:用一个方法定义一个接口
AppointBookingObserver
。将该接口嵌套在
调度程序
类上。将
Person
声明为
实现调度程序。AppointmentBookingObserver
。然后将
bookAppointment
上的第二个参数定义为
AppointmentBookingObserver
对象。
bookAppointment
方法最终将调用单一接口方法:
observer.appointmenthasbooked
。这是可行的,但对于这样一个简单的单一回调场景来说似乎有些过头了。只需传递
this::appointmentHasBeenBooked
就会更简单、更清晰

这里没有线程。因此需要执行器、
Runnable
,或者关注线程安全


如果您希望了解我的实际用例场景的详细信息,而不是上面这个人为的Person Scheduler示例,请参阅我的另一个问题。

您认为的方法引用可以只是一种类型

然后

Scheduler scheduler = new Scheduler();
Person person = new Person();

scheduler.bookAppointment( person.id , person::appointmentBooked);

在的评论中已经确认,不为无参数的
void
操作添加另一个功能接口的原因是
Runnable
已经达到了目的

所以你可以用

public class Scheduler {
    public void bookAppointment(UUID id, Runnable methRef) {
        … book the appointment
        methRef.run();
    }
}
作为

public class Person { 
    public void fooBar() {
        Scheduler scheduler = … ;
        scheduler.bookAppointment(this.id, this::appointmentBooked) ;  // Asking the scheduler to eventually book an appointment for this person, and when accomplished, notify this person by invoking the passed method.
        …
    }
    // Callback - To be invoked after the `Scheduler` object succeeds in booking an appointment. 
    public void appointmentBooked() {
        …
    }
}
public class Person { 
    public void fooBar() {
        Scheduler scheduler = … ;
        scheduler.bookAppointment(this.id, this, Person::appointmentBooked) ;  // Asking the scheduler to eventually book an appointment for this person, and when accomplished, notify this person by invoking the passed method.
        …
    }
    // Callback - To be invoked after the `Scheduler` object succeeds in booking an appointment. 
    public void appointmentBooked() {
        …
    }
}
但还有一种选择

public class Scheduler {
    public <T> void bookAppointment(UUID id, T instance, Consumer<T> methRef) {
        … book the appointment
        methRef.accept(instance);
    }
}
这强调了问题的“实例方法引用”方面,尽管此构造不强制要求
使用者
是这样一个方法引用,但使使用这样一个方法引用更容易


另外,
Person::appointmentBooked
是一个非捕获方法引用,它将被评估为
使用者
实例,该实例将在后续调用中重用。

我的问题中不涉及线程,因此不需要
Runnable
@Basil。不涉及多线程。Runnable在这里只是一个函数接口。啊,我想我明白了,只需使用
Runnable
作为一个方便的预定义函数接口,而不是编写我自己的嵌套接口。这么简单。我将不得不考虑这一点。谢谢@巴兹尔:是的,这是最简单和最符合你需要的。在这里查看我多次关注的其他选项。所有这些似乎都不适合调用没有返回值的无参数方法的简单情况。但是
Runnable
就是这样。我唯一担心的是,如果有人阅读我的代码,看到一个
可运行的
,就会认为线程即将到来。在该页面或其他地方是否有其他界面可以工作?我想我可以发明自己的代码,在我的代码库中使用。但这似乎是许多人的共同需要。
public class Person { 
    public void fooBar() {
        Scheduler scheduler = … ;
        scheduler.bookAppointment(this.id, this, Person::appointmentBooked) ;  // Asking the scheduler to eventually book an appointment for this person, and when accomplished, notify this person by invoking the passed method.
        …
    }
    // Callback - To be invoked after the `Scheduler` object succeeds in booking an appointment. 
    public void appointmentBooked() {
        …
    }
}