Anonymous Classes

Classes without names

5 min read

Anonymous Classes in Java

An anonymous class is a class with no name, defined and instantiated in a single expression. It's useful for one-time implementations.

Anonymous Class Characteristics

  • No name - defined inline where needed
  • Can extend a class OR implement an interface (not both)
  • Cannot have explicit constructors
  • Can access final/effectively final local variables
  • Often replaced by lambdas in Java 8+

✓ Java 8+: For functional interfaces (single abstract method), prefer lambdas over anonymous classes. They're more concise!

🔑 Syntax: new InterfaceOrClass() { implementation }

Code Examples

Anonymous class implementing interface

java
1// Anonymous class implementing interface
2interface Greeting {
3    void greet(String name);
4}
5
6public class Demo {
7    public static void main(String[] args) {
8        // Anonymous class - inline implementation
9        Greeting formal = new Greeting() {
10            @Override
11            public void greet(String name) {
12                System.out.println("Good morning, " + name);
13            }
14        };
15        
16        Greeting casual = new Greeting() {
17            @Override
18            public void greet(String name) {
19                System.out.println("Hey, " + name + "!");
20            }
21        };
22        
23        formal.greet("Mr. Smith");  // Good morning, Mr. Smith
24        casual.greet("John");        // Hey, John!
25    }
26}
27
28// With Java 8 lambda (much cleaner for single-method interfaces)
29Greeting lambda = name -> System.out.println("Hi, " + name);

Anonymous class extending abstract/concrete class

java
1// Anonymous class extending a class
2abstract class Animal {
3    abstract void makeSound();
4    
5    void sleep() {
6        System.out.println("Sleeping...");
7    }
8}
9
10public class Demo {
11    public static void main(String[] args) {
12        // Anonymous class extending Animal
13        Animal dog = new Animal() {
14            @Override
15            void makeSound() {
16                System.out.println("Woof!");
17            }
18            
19            // Can add additional methods
20            void fetch() {
21                System.out.println("Fetching...");
22            }
23        };
24        
25        dog.makeSound();  // Woof!
26        dog.sleep();      // Sleeping...
27        // dog.fetch();   // ERROR! fetch() not in Animal type
28        
29        // Extending concrete class
30        Thread customThread = new Thread() {
31            @Override
32            public void run() {
33                System.out.println("Custom thread running");
34            }
35        };
36        customThread.start();
37    }
38}

Anonymous class with parent constructor

java
1// Anonymous class with constructor arguments
2class Greeter {
3    private String greeting;
4    
5    public Greeter(String greeting) {
6        this.greeting = greeting;
7    }
8    
9    public void greet(String name) {
10        System.out.println(greeting + ", " + name);
11    }
12}
13
14public class Demo {
15    public static void main(String[] args) {
16        // Anonymous class with parent constructor argument
17        Greeter custom = new Greeter("Welcome") {
18            @Override
19            public void greet(String name) {
20                System.out.println("🎉 " + name + "!");
21                super.greet(name);  // Can call parent method
22            }
23        };
24        
25        custom.greet("Alice");
26        // Output:
27        // 🎉 Alice!
28        // Welcome, Alice
29    }
30}

Event listeners and Comparators

java
1// Common use cases: Event listeners, Comparators
2import java.util.*;
3
4public class Demo {
5    public static void main(String[] args) {
6        // Comparator - anonymous class
7        List<String> names = Arrays.asList("Charlie", "Alice", "Bob");
8        
9        Collections.sort(names, new Comparator<String>() {
10            @Override
11            public int compare(String s1, String s2) {
12                return s1.length() - s2.length();  // By length
13            }
14        });
15        
16        // Lambda equivalent (Java 8+) - prefer this!
17        names.sort((s1, s2) -> s1.length() - s2.length());
18        // Or: names.sort(Comparator.comparingInt(String::length));
19        
20        // Runnable - anonymous class
21        new Thread(new Runnable() {
22            @Override
23            public void run() {
24                System.out.println("Running!");
25            }
26        }).start();
27        
28        // Lambda equivalent - much cleaner!
29        new Thread(() -> System.out.println("Running!")).start();
30    }
31}
32
33// When to still use anonymous class over lambda:
34// 1. Need to implement multiple methods
35// 2. Need to extend a class (not interface)
36// 3. Need instance initialization block
37// 4. Need to reference 'this' as the anonymous class

Use Cases

  • Event handlers and listeners
  • Comparators for sorting
  • Thread/Runnable implementations
  • One-time interface implementations
  • Test doubles and mocks
  • Strategy pattern implementations

Common Mistakes to Avoid

  • Using when lambda is cleaner
  • Trying to implement multiple interfaces
  • Forgetting semicolon after closing brace
  • Memory leaks from outer reference
  • Adding methods not in parent type
  • Complex logic in anonymous class