Home » Java Anonymous Classes Tutorial

Java Anonymous Classes Tutorial

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.

You may also like