2

I have a button and I want a text to be displayed when I hover the mouse over the button.

Both of these work but can they be used interchangeably?

// First
EventHandler<MouseEvent> eventHandler = new EventHandler<MouseEvent>() {
    @Override
    public void handle(MouseEvent e) {
        System.out.println("Hello World");
    }
};
button.setOnMouseEntered(eventHandler);

// Second. Lambda expression.
button.setOnMouseEntered(e -> {
    System.out.println("Hello ");
});

I don't quite understand the first one. I suppose that EventHandler<MouseEvent> is the type and eventHandler is the name of the object. Right?

Michiel Leegwater
  • 1,172
  • 4
  • 11
  • 27
Zoltan King
  • 1,964
  • 4
  • 18
  • 38

4 Answers4

2

Yes, they both will execute the same code.

The first one is an so-called anonymous class. This means that you override the methods (handle in this case) of the inherited interface directly without having to do that with additional classes/interfaces.

You then pass the handler instance to the setOnMouseEntered method.

The lambda expression does this also but since the method requires a certain object type, you can write it shorter with the lambda expression.

e is basically the same as eventHandler

apt-get_install_skill
  • 2,818
  • 10
  • 27
1

The first one is an anonymous inner class, where the handle method is overridden. This was the way to do listeners and handlers before lambda expressions. Now, if the class is an functional interface (only 1 abstract method, like the EventHandler in your case with its only method, handle) then a lambda expression can be used instead of anonim class.

The two methods are indeed the same, but using lambdas are preferred, because the code will be much more compact and easier to understand.

The Head Rush
  • 3,157
  • 2
  • 25
  • 45
Gtomika
  • 845
  • 7
  • 24
1

Both of the answers already provided are good, but I wanted to add another consideration.

Whenever possible, lambdas are preferable, not only because they're easier to read, but they also result in very different bytecode when compiled.

In the first example, the compiler creates a separate class (for example: OuterClass$1). This class has to be instantiated on each invocation, which will have to be garbage collected at some point.

In the second example, the lambda is compiled to a method that's local to the containing class. This means that it's a just a simple method invocation.

Depending on how frequently it's invoked, this may be an important consideration.

Andy Senn
  • 649
  • 5
  • 13
0

I believe the first example could be explicitly written as:

private class MouseHandler implements EventHandler<MouseEvent> {
    public void handle(MouseEvent e) {
        System.out.println("Hello World");
    }
}
button.setOnMouseEntered(new MouseHandler());

This can be reduced via the anonymous class and more by the lambda expression. My understanding is that this is only possible because EventHandler is a functional interface. What is a functional interface in Java SKO

neutrino_logic
  • 1,289
  • 1
  • 6
  • 11