Question

Learning about anonymous classes and have this from Oracle. I am hoping someone can show me what this would look like if I did not use anonymous classes. How would I have done this with a new class?

import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;

public class HelloWorld extends Application {
    public static void main(String[] args) {
        launch(args);
    }

    @Override
    public void start(Stage primaryStage) {
        primaryStage.setTitle("Hello World!");
        Button btn = new Button();
        btn.setText("Say 'Hello World'");
        btn.setOnAction(new EventHandler<ActionEvent>() {

            @Override
            public void handle(ActionEvent event) {
                System.out.println("Hello World!");
            }
        });

        StackPane root = new StackPane();
        root.getChildren().add(btn);
        primaryStage.setScene(new Scene(root, 300, 250));
        primaryStage.show();
    }
}

In this example, the method invocation btn.setOnAction specifies what happens when you select the Say 'Hello World' button. This method requires an object of type EventHandler. The EventHandler interface contains only one method, handle. Instead of implementing this method with a new class, the example instead uses an anonymous class expression. Notice that this expression is the argument passed to the btn.setOnAction method.

Source: http://docs.oracle.com/javase/tutorial/java/javaOO/anonymousclasses.html

Was it helpful?

Solution

Just create a new non-anonymous class somewhere. I did it as a nested class inside HelloWorld:

public class HelloWorld extends Application {
    public static void main(String[] args) {
        launch(args);
    }

    @Override
    public void start(Stage primaryStage) {
        primaryStage.setTitle("Hello World!");
        Button btn = new Button();
        btn.setText("Say 'Hello World'");
        btn.setOnAction(new MyEventHandler());

        StackPane root = new StackPane();
        root.getChildren().add(btn);
        primaryStage.setScene(new Scene(root, 300, 250));
        primaryStage.show();
    }

    public class MyEventHandler implements EvenHandler<ActionEven>
    {
        @Override
        public void handle(ActionEvent event) {
            System.out.println("Hello World!");
        }
    }
}

OTHER TIPS

The EventHandler class is stateless, so all the instances of this class are functionally equivalent. We just need one single instance of this class to perform the handle operation because the functionality of this method depends only on the parameter passed to it, it does not depend on the state of the object as it does not have any.Thus, it should be a singleton. Using Anonymous classes will create a new instance every time a call to setOnAction is executed. To avoid this, you can consider storing an instance of the EvenHandler implementation in a private static final field and reusing it by using static factory method as below:

public class HandlerProvider{
private static final EvenHandler<ActionEvent> EVENT_HANDLER=new ActionEventHandler();

public static EvenHandler<ActionEvent> getEventHandler(){
return EVENT_HANDLER;
}
private static class ActionEventHandler implements EvenHandler<ActionEvent>
    {
        @Override
        public void handle(ActionEvent event) {
            //your action goes here
        }
    }
}

In this way you can avoid unnecessary object creation on each method call.

I don't know what to do.

  1. Create a new class that implements the desired interface.1
  2. Move the code from the anonymous class to the new class.
  3. Wherever your anonymous class was used, change it by a new instance of this class.

Applying this to the provided example:

class FooEventHandler implements EventHandler<ActionEvent>() {
    @Override
    public void handle(ActionEvent event) {
        System.out.println("Hello World!");
    }
}

public class HelloWorld extends Application {
    //...
    @Override
    public void start(Stage primaryStage) {
        //...
        btn.setOnAction(new FooEventHandler());
        //...
    }
}

1: Note that the class that implements the interface will follow the rules of any simple class you write, this means it can be a top level class, an inner class or a static inner class.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top