简体   繁体   中英

How do you get event notifications back to the main program class of a Java console app?

I'm coming to Java from C#, and I'm really just trying to figure out how to do things in Java world. I'm running Java 8 in IntelliJ IDEA. I found this explaining events in Java as basically being hand-made through manual registration and an interface method call. The code example has enough problems that I assume it was never compiled. After cleaning that up a bit I have this:

Interface MetronomeEvent:

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();
    }
}

Main console application:

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());
    }
}

The one remaining error is source.addMetronomeEventListener(this); where the compiler complains that it cannot reference MyApp.this from a static context. That makes sense, but I don't see any way then that I could, after implementing the MetronomeEvent interface on the main program class, actually pass it to source.addMetronomeEventListener() for registration. Is it impossible to directly register the main program class for events? Am I supposed to create and register a Listener class that implements MetronomeEvent and will act on behalf of the main application? Like this?

public class Listener implements MetronomeEvent {
    public void Tick(Date tickDate){
        System.out.println(tickDate.toString());
    }
}

And then:

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();
}

Based on Vince Emigh's comment/answer I was led to this Oracle doc on lamda expressions and to this one on method references . I've found 3 ways to do this so far.

1) Anonymous 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 expression:

source.addMetronomeEventListener(d -> System.out.println("lambda:\n"+d.toString()));

3) Method reference, which is the closest to what I am accustomed to. A method is defined in the main class:

public static void processTick(Date tickDate){
    System.out.println("method reference:");
    System.out.println(tickDate.toString());
}

...and then in the body of main() it is added as an event handler like this:

source.addMetronomeEventListener(MainApp::processTick);

This is not about events, it's about main() and static methods in general.

I would suggest writing your main() as

public static void main(String[] args) {
    new MainApp(args).execute();
}

This way you're immediately jumping from static function world into object-oriented world.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM