An anonymous class in Java is a type of inner class that is defined without a class name and is declared and instantiated all in a single expression.
Anonymous classes are useful when you need a one-time use implementation of an interface or subclass and don't want to write a full class definition.
They allow for concise code by providing a way to create a new class on the fly and override methods immediately.
In this tutorial, we’ll cover the basics of anonymous classes, their use cases, and multiple examples to demonstrate how they work in Java.
1. What is an Anonymous Class?
An anonymous class is an inner class that:
Has no name: It's declared and instantiated in one expression.
Implements an interface or extends a class.
Overrides methods immediately after creation.
Typically used to provide a short implementation when the class is only needed once.
2. Syntax of Anonymous Classes
The syntax for an anonymous class in Java is:
new () { // Method implementations or overrides };
3. Anonymous Class with an Interface
You can use an anonymous class to implement an interface directly. For example, consider an interface with a single method display():
Example: Anonymous Class Implementing an Interface
interface Message { void display(); } public class AnonymousClassExample { public static void main(String[] args) { // Anonymous class implementing the Message interface Message message = new Message() { @Override public void display() { System.out.println("Hello from the anonymous class!"); } }; // Call the display method message.display(); } }
Explanation:
We create an anonymous class that implements the Message interface and provides an implementation for the display() method.
The class has no name and is defined inline at the point of instantiation.
Output:
Hello from the anonymous class!
4. Anonymous Class with a Class (Extending a Class)
Anonymous classes can also extend a class. Let's say you have a class Person with a method sayHello():
Example: Anonymous Class Extending a Class
class Person { public void sayHello() { System.out.println("Hello from Person"); } } public class AnonymousClassWithClassExample { public static void main(String[] args) { // Anonymous class extending the Person class Person person = new Person() { @Override public void sayHello() { System.out.println("Hello from the anonymous subclass of Person"); } }; // Call the overridden method person.sayHello(); } }
Explanation:
We extend the Person class and override the sayHello() method using an anonymous class.
The anonymous class is instantiated and used immediately.
Output:
Hello from the anonymous subclass of Person
5. Anonymous Class with Event Listeners (Real-World Use Case)
Anonymous classes are commonly used in event handling scenarios, such as with GUI components or user interaction. For example, in Java’s Swing library, you can use an anonymous class to handle a button click event.
Example: Anonymous Class in Event Handling (Java Swing)
import javax.swing.JButton; import javax.swing.JFrame; import javax.swing.JOptionPane; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; public class AnonymousClassEventExample { public static void main(String[] args) { // Create a JFrame window JFrame frame = new JFrame("Anonymous Class Event Example"); frame.setSize(300, 200); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); // Create a JButton JButton button = new JButton("Click Me"); // Add an ActionListener using an anonymous class button.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { JOptionPane.showMessageDialog(frame, "Button Clicked!"); } }); // Add the button to the frame and make it visible frame.add(button); frame.setVisible(true); } }
Explanation:
We create a button and use an anonymous class to handle its ActionListener.
The anonymous class is instantiated and passed to the addActionListener() method to handle the button click event.
Output: When the user clicks the button, a pop-up message “Button Clicked!” will appear.
6. Anonymous Class with Constructor Parameters
Anonymous classes can also capture and use variables from the surrounding scope, including constructor parameters. However, these variables must be final or effectively final (meaning they are not modified after being initialized).
Example: Anonymous Class with Constructor Parameter
class Animal { private String name; public Animal(String name) { this.name = name; } public void sound() { System.out.println(name + " makes a sound."); } } public class AnonymousClassConstructorExample { public static void main(String[] args) { String animalName = "Dog"; // Anonymous class using the constructor of Animal class Animal dog = new Animal(animalName) { @Override public void sound() { System.out.println(animalName + " barks!"); } }; // Call the overridden method dog.sound(); } }
Explanation:
We pass a constructor argument (animalName) to the Animal class, and the anonymous class overrides the sound() method.
The animalName variable is captured inside the anonymous class and used in the overridden method.
Output:
Dog barks!
7. Anonymous Classes and Variable Scope
Anonymous classes can access variables from the enclosing scope, but only if they are final or effectively final. This ensures that the value remains consistent throughout the lifetime of the anonymous class.
Example: Anonymous Class and Final Variables
public class AnonymousClassScopeExample { public static void main(String[] args) { // Effectively final variable String greeting = "Hello"; // Anonymous class using the greeting variable Runnable runnable = new Runnable() { @Override public void run() { System.out.println(greeting + " from the anonymous class!"); } }; // Call the run method runnable.run(); } }
Explanation:
The variable greeting is effectively final (its value is not modified after initialization).
The anonymous class can use greeting within the run() method because it is effectively final.
Output:
Hello from the anonymous class!
8. Anonymous Classes vs Lambda Expressions
In Java 8 and later, lambda expressions can be used as a more concise alternative to anonymous classes when implementing functional interfaces (interfaces with a single abstract method). Lambdas offer simpler syntax for this purpose.
Example: Anonymous Class vs Lambda Expression
Anonymous Class:
Runnable anonymousClassRunnable = new Runnable() { @Override public void run() { System.out.println("Running from anonymous class"); } }; anonymousClassRunnable.run();
Lambda Expression (Java 8+):
Runnable lambdaRunnable = () -> System.out.println("Running from lambda expression"); lambdaRunnable.run();
Explanation:
Both the anonymous class and lambda expression implement the Runnable interface, but the lambda expression provides a shorter, more readable syntax.
Lambda expressions are generally preferred when using functional interfaces in Java 8+.
Output for Both:
Running from anonymous class Running from lambda expression
9. Anonymous Class with Multiple Methods (More Complex Example)
In an anonymous class, you can override multiple methods when extending an abstract class or implementing an interface with more than one method.
Example: Anonymous Class with Multiple Methods
interface Vehicle { void start(); void stop(); } public class AnonymousClassMultipleMethodsExample { public static void main(String[] args) { // Anonymous class implementing two methods Vehicle car = new Vehicle() { @Override public void start() { System.out.println("Car is starting"); } @Override public void stop() { System.out.println("Car is stopping"); } }; // Call both methods car.start(); car.stop(); } }
Explanation:
The Vehicle interface has two methods (start() and stop()), and we provide an anonymous class that implements both.
We can call both methods on the car object.
Output:
Car is starting Car is stopping
10. Limitations of Anonymous Classes
While anonymous classes are useful, they come with certain limitations:
Cannot have a constructor: You can pass arguments to the superclass or interface constructor, but you cannot define a constructor in the anonymous class itself.
Cannot be reused: Since anonymous classes are unnamed and instantiated only once, they cannot be reused in different parts of the code.
Cannot define static members: Anonymous classes cannot contain static fields or methods.
Conclusion
Anonymous classes in Java provide a powerful, concise way to create one-time-use classes that implement interfaces or extend existing classes. They are particularly useful in event handling, callbacks, and scenarios where you need a quick implementation without the need for a full class definition.
Key Points:
Anonymous classes are used to implement interfaces or extend classes inline.
They are commonly used for event listeners, callbacks, and functional programming.
Autoboxing and lambda expressions (in Java 8+) provide a more concise syntax for certain use cases of anonymous classes.
By understanding and using anonymous classes effectively, you can write more concise and flexible Java code in situations where creating a full class is unnecessary.