如何将事件通知返回到 Java 控制台应用程序的主程序 class?
How do you get event notifications back to the main program class of a Java console app?
我是从 C# 转到 Java,我真的只是想弄清楚如何在 Java 世界中做事。我在 IntelliJ IDEA 中 运行 Java 8。我发现 this 将 Java 中的事件解释为基本上是通过手动注册和接口方法调用手工制作的。代码示例有很多问题,我认为它从未被编译过。稍微清理一下后,我得到了这个:
接口节拍器事件:
public interface MetronomeEvent {
void Tick(Date tickDate);
}
Class EventFiringSource:
public class EventFiringSource {
// Our collection of classes that are subscribed as listeners of our
protected List<MetronomeEvent> _listeners=new ArrayList();
// Method for listener classes to register themselves
public void addMetronomeEventListener(MetronomeEvent listener)
{
_listeners.add(listener);
}
// "fires" the event
protected void fireMetronomeEvent()
{
if (_listeners != null && !_listeners.isEmpty())
{
for (MetronomeEvent e:_listeners)
{
e.Tick(new Date());
}
}
}
public void Start()
{
fireMetronomeEvent();
}
}
主控制台应用程序:
public class MainApp implements MetronomeEvent {
public static void main(String[] args) {
EventFiringSource source = new EventFiringSource();
source.addMetronomeEventListener(this); // Adds itself as a listener for the event
source.Start();
}
public void Tick(Date tickDate)
{
System.out.println(tickDate.toString());
}
}
剩下的一个错误是 source.addMetronomeEventListener(this);
,其中编译器抱怨它无法从静态上下文中引用 MyApp.this
。这是有道理的,但我看不出有什么办法可以在主程序 class 上实现 MetronomeEvent 接口后,实际将其传递给 source.addMetronomeEventListener()
进行注册。难道不能直接在主程序class上注册事件吗?我是否应该创建并注册一个监听器 class 来实现 MetronomeEvent 并将代表主应用程序执行操作?像这样?
public class Listener implements MetronomeEvent {
public void Tick(Date tickDate){
System.out.println(tickDate.toString());
}
}
然后:
public static void main(String[] args) {
EventFiringSource source = new EventFiringSource();
Listener l=new Listener();
source.addMetronomeEventListener(l); // Adds another object to listen on behalf of main()
source.Start();
}
基于 Vince Emigh 的 comment/answer 我被引导 to this Oracle doc on lamda expressions and to this one on method references。到目前为止,我已经找到了 3 种方法。
1) 匿名 class:
source.addMetronomeEventListener(
new MetronomeEvent() {
@Override
public void Tick(Date tickDate) {
System.out.println("anonymous class:");
System.out.println(tickDate.toString());
}
}
); // Adds itself as a listener for the event
2) Lambda 表达式:
source.addMetronomeEventListener(d -> System.out.println("lambda:\n"+d.toString()));
3) 方法参考,最接近我习惯的。 main中定义了一个方法class:
public static void processTick(Date tickDate){
System.out.println("method reference:");
System.out.println(tickDate.toString());
}
...然后在 main() 的主体中将其添加为事件处理程序,如下所示:
source.addMetronomeEventListener(MainApp::processTick);
这与事件无关,它与 main()
和一般的静态方法有关。
我建议将 main() 写成
public static void main(String[] args) {
new MainApp(args).execute();
}
这样您就可以立即从静态函数世界跳转到面向对象的世界。
我是从 C# 转到 Java,我真的只是想弄清楚如何在 Java 世界中做事。我在 IntelliJ IDEA 中 运行 Java 8。我发现 this 将 Java 中的事件解释为基本上是通过手动注册和接口方法调用手工制作的。代码示例有很多问题,我认为它从未被编译过。稍微清理一下后,我得到了这个:
接口节拍器事件:
public interface MetronomeEvent {
void Tick(Date tickDate);
}
Class EventFiringSource:
public class EventFiringSource {
// Our collection of classes that are subscribed as listeners of our
protected List<MetronomeEvent> _listeners=new ArrayList();
// Method for listener classes to register themselves
public void addMetronomeEventListener(MetronomeEvent listener)
{
_listeners.add(listener);
}
// "fires" the event
protected void fireMetronomeEvent()
{
if (_listeners != null && !_listeners.isEmpty())
{
for (MetronomeEvent e:_listeners)
{
e.Tick(new Date());
}
}
}
public void Start()
{
fireMetronomeEvent();
}
}
主控制台应用程序:
public class MainApp implements MetronomeEvent {
public static void main(String[] args) {
EventFiringSource source = new EventFiringSource();
source.addMetronomeEventListener(this); // Adds itself as a listener for the event
source.Start();
}
public void Tick(Date tickDate)
{
System.out.println(tickDate.toString());
}
}
剩下的一个错误是 source.addMetronomeEventListener(this);
,其中编译器抱怨它无法从静态上下文中引用 MyApp.this
。这是有道理的,但我看不出有什么办法可以在主程序 class 上实现 MetronomeEvent 接口后,实际将其传递给 source.addMetronomeEventListener()
进行注册。难道不能直接在主程序class上注册事件吗?我是否应该创建并注册一个监听器 class 来实现 MetronomeEvent 并将代表主应用程序执行操作?像这样?
public class Listener implements MetronomeEvent {
public void Tick(Date tickDate){
System.out.println(tickDate.toString());
}
}
然后:
public static void main(String[] args) {
EventFiringSource source = new EventFiringSource();
Listener l=new Listener();
source.addMetronomeEventListener(l); // Adds another object to listen on behalf of main()
source.Start();
}
基于 Vince Emigh 的 comment/answer 我被引导 to this Oracle doc on lamda expressions and to this one on method references。到目前为止,我已经找到了 3 种方法。
1) 匿名 class:
source.addMetronomeEventListener(
new MetronomeEvent() {
@Override
public void Tick(Date tickDate) {
System.out.println("anonymous class:");
System.out.println(tickDate.toString());
}
}
); // Adds itself as a listener for the event
2) Lambda 表达式:
source.addMetronomeEventListener(d -> System.out.println("lambda:\n"+d.toString()));
3) 方法参考,最接近我习惯的。 main中定义了一个方法class:
public static void processTick(Date tickDate){
System.out.println("method reference:");
System.out.println(tickDate.toString());
}
...然后在 main() 的主体中将其添加为事件处理程序,如下所示:
source.addMetronomeEventListener(MainApp::processTick);
这与事件无关,它与 main()
和一般的静态方法有关。
我建议将 main() 写成
public static void main(String[] args) {
new MainApp(args).execute();
}
这样您就可以立即从静态函数世界跳转到面向对象的世界。