Lesson 10 | Inner classes and Anonymous Classes |
Objective | Explain anonymous classes as a special case of inner classes. |
Java Anonymous Inner Classes
Anonymous classes are a special case of
local inner classes that are declared without a name.
They are single-use classes that are created and defined at the same time.
They are typically used to declare an instance of a class that implements an event listener interface or extends an event adapter class.
There are two forms for their syntax, depending on whether they implement an interface or extend another class:
- Anonymous class declaration is automatically derived from a class instance creation expression.
- An anonymous class is never abstract.
- An anonymous class is always an inner class.
- An anonymous class is never static .
- An anonymous class is always implicitly final.
Implementing an interface
new InterfaceName() {
// Implement interface methods
}
new SuperClassName(arguments) {
// Class body
}
In the first form, the anonymous class is declared as implementing the specified interface name.
No implements clause is used and the interface name is supplied as the type of object being created. The anonymous class is responsible for implementing all of the methods of the interface. When an anonymous inner class is defined as an interface, the
Object
class is its direct superclass.
Since the
Object
class does not have a constructor that takes arguments, no arguments may be supplied when an anonymous class is created as an interface.
In the second form, the superclass of the class being defined is specified. No extends clause is used. The arguments (if any) that are supplied are passed to the
superclass constructor when the object is created. The superclass must have a constructor with a signature that accepts the arguments.
Since the class being declared does not have a name, no constructor is specified in the class body. An anonymous class may not have any modifiers.
The
Anonymous program illustrates the use of anonymous inner classes.
Anonymous Program
The Anonymous
program illustrates the use of anonymous inner classes.
It creates a window program with a moving button. The Anonymous()
constructor uses an anonymous inner class to create an object that implements the ActionListener
interface to handle the clicking of the button. This object provides an implementation of the actionPerformed()
method. Note that the button
variable is declared as final
. The Anonymous()
constructor also uses an anonymous inner class that extends the WindowAdapter
class to handle the closing of the application window.
The Anonymous Java Program
import java.awt.*;
import java.awt.event.*;
class Anonymous extends Frame {
public static void main(String[] args) {
new Anonymous();
}
Anonymous() {
setLayout(null);
final Button button = new Button("Click me!");
button.setBounds(100,100,100,100);
button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
if (button.getLocation().x == 100)
button.setBounds(200,200,100,100);
else
button.setBounds(100,100,100,100);
}
});
add(button);
addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
setSize(400,400);
setVisible(true);
}
}
Java AWT code modernized and rewritten
To modernize the given Java code, we can make use of more recent Java APIs and better practices. The `java.awt` package, while still available, is largely considered outdated for most GUI applications, and modern Java development typically uses JavaFX for building graphical user interfaces (GUIs).
Below is the rewritten code using JavaFX, which is the recommended framework for GUI development in modern Java applications:
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.Pane;
import javafx.stage.Stage;
public class Anonymous extends Application {
@Override
public void start(Stage primaryStage) {
Pane root = new Pane();
Button button = new Button("Click me!");
button.setLayoutX(100);
button.setLayoutY(100);
button.setPrefSize(100, 100);
button.setOnAction(e -> {
if (button.getLayoutX() == 100) {
button.setLayoutX(200);
button.setLayoutY(200);
}else {
button.setLayoutX(100);
button.setLayoutY(100);
}
});
root.getChildren().add(button);
Scene scene = new Scene(root, 400, 400);
primaryStage.setTitle("Anonymous");
primaryStage.setScene(scene);
primaryStage.setOnCloseRequest(e -> System.exit(0));
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
Key Changes:
- JavaFX Instead of AWT:
- JavaFX is used to replace the deprecated `java.awt` and `java.awt.event` packages. JavaFX is the modern standard for creating GUIs in Java.
- Instead of using `Frame`, we use `Stage`, `Scene`, and `Pane` to create the window and layout
- Event Handling:
- In place of `ActionListener`, JavaFX provides lambda expressions (or method references) for handling events, making the code more concise and readable. The `button.setOnAction()` method is used instead of `button.addActionListener()`.
- Button Layout:
- JavaFX uses `setLayoutX()` and `setLayoutY()` methods to position elements, which are more intuitive and flexible than `setBounds()` in AWT.
- Window Closing:
- In JavaFX, window close events are handled using `setOnCloseRequest()`, which directly connects to the window closing event without needing a separate `WindowAdapter`.
Summary:
This modernized code leverages JavaFX, which is the preferred choice for building Java GUIs today. The use of lambda expressions for event handling also simplifies the code, making it easier to read and maintain.
Which variables of the encapsulating class can an inner class access, if the inner class is defined in an instance method of the encapsulating class?
(Select 4 options: )
- All static variables
- All final instance variables
- All instance variables
- All automatic variables.
- All final automatic variables
Answer: a, b, c, e
Explanation: Consider the following code:
public class TestClass{
static int si = 10; int ii = 20;
public void inner(){
int ai = 30; //automatic variable
final int fai = 40; //automatic final variable
class Inner{
public Inner() { System.out.println(si+" "+ii+" "+fai); }
}
new Inner();
}
public static void main(String[] args){ new TestClass().inner(); }
}
Because method inner is an instance method (i.e. non-static method), si, ii, and fai are accessible in class Inner. Note that 'ai' is not accessible.
If method inner() were a static method, "ii" would have been inaccessible.