Introducción a clases anónimas en Java

En Java, las clases anónimas son una característica poderosa y poco conocida que nos permite crear implementaciones puntuales de interfaces, clases abstractas o subclases sin necesidad de definir una clase con nombre. Esto resulta especialmente útil cuando necesitamos una única instancia con un comportamiento específico, como ocurre frecuentemente en la gestión de eventos o en la creación de funciones lambda.

Para entenderlo mejor, partimos de un ejemplo clásico: imaginemos que tenemos una interfaz llamada Comando que define métodos como nombre y descripcion. La forma tradicional de implementar esta interfaz sería crear una clase concreta, por ejemplo AyudaComando, que implementa esos métodos y luego instanciarla para usarla. Así, podríamos tener algo como esto:

public interface Comando {
    String nombre();
    String descripcion();
}

public class AyudaComando implements Comando {
    @Override
    public String nombre() {
        return "ayuda";
    }

    @Override
    public String descripcion() {
        return "Muestra los parámetros y la forma de usar";
    }
}

Luego, al crear una instancia de AyudaComando y asignarla a una variable de tipo Comando, podemos llamar a sus métodos sin problema.

Sin embargo, cuando queremos evitar crear una clase completa para una implementación que solo usaremos una vez, entran en juego las clases anónimas. En Java, aunque no podemos instanciar directamente una interfaz, sí podemos crear una clase anónima que la implemente al vuelo. Esto se hace usando la sintaxis de new seguida del nombre de la interfaz y un bloque de llaves donde implementamos los métodos requeridos. Por ejemplo:

Comando opciones = new Comando() {
    @Override
    public String nombre() {
        return "opciones";
    }

    @Override
    public String descripcion() {
        return "Muestra las opciones del programa";
    }
};

Aquí, opciones es una instancia de una clase anónima que implementa Comando. Esta clase no tiene nombre, y el compilador de Java le asigna internamente un nombre como Main$1 o similar. Aunque no podemos crear más instancias de esta clase anónima ni referirnos a ella por nombre, sí podemos usar la variable opciones para llamar a sus métodos normalmente.

Además, esta técnica no se limita a interfaces. También podemos usar clases anónimas para implementar clases abstractas al vuelo. Por ejemplo, si tenemos una clase abstracta AbstractComando con métodos abstractos, podemos crear una instancia anónima que los implemente directamente:

AbstractComando login = new AbstractComando() {
    @Override
    public String nombre() {
        return "login";
    }

    @Override
    public String descripcion() {
        return "Permite iniciar sesión";
    }
};

De nuevo, el compilador asignará un nombre interno a esta clase anónima, como Main$2, y podremos usar login para acceder a sus métodos.

Un uso adicional de las clases anónimas es para crear subclases de clases concretas y sobrescribir métodos puntualmente. Por ejemplo, si queremos modificar el comportamiento de un método de la clase Random, podemos hacerlo así:

Random randomPersonalizado = new Random() {
    @Override
    public int nextInt(int bound) {
        // Lógica personalizada
        System.out.println("Generando número aleatorio personalizado");
        return super.nextInt(bound);
    }
};

Aquí, randomPersonalizado es una instancia de una subclase anónima de Random que sobrescribe el método nextInt. Esto nos permite modificar o extender el comportamiento de clases existentes sin crear una clase con nombre.

Aunque las clases anónimas no son reutilizables porque no tienen nombre y no podemos instanciarlas más de una vez, son ideales para implementaciones rápidas y puntuales. Por eso, en Java es común encontrarlas en la creación de event listeners o en funciones lambda, donde se necesita definir un comportamiento concreto sin la sobrecarga de crear una clase completa.

En definitiva, las clases anónimas nos ofrecen una forma concisa y eficiente de implementar interfaces, clases abstractas o subclases para casos de uso específicos y de un solo uso, facilitando la escritura de código más limpio y directo.

Lista de reproducción
  1. 1
    ¿Cómo funciona Comparator en Java?
    10 minutos
  2. 2
    ¿Para qué sirve Override?
    4 minutos
  3. 3
    Cómo usar la clase Properties en Java
    14 minutos
  4. 4
    Interfaces funcionales y funciones flecha
    8 minutos
  5. 5
    Bloque static de Java: inicializadores estáticos y otros usos
    7 minutos
  6. 6
    import static, ¿para qué sirve?
    3 minutos
  7. 7
    Uso de Optional en Java
    10 minutos
  8. 8
    Introducción al Scanner de Java
    11 minutos
  9. 9
    ¿Para qué sirve el modificador static de Java?
    6 minutos
  10. 10
    Funciones variádicas en Java
    6 minutos
  11. 11
    Inner classes en Java
    8 minutos
  12. 12
    var en Java: una introducción para gente nueva
    7 minutos
  13. 13
    Switch expressions en Java
    10 minutos
  14. 14
    Java: del instanceof al Pattern Matching
    7 minutos
  15. 15
    Sealed classes en Java
    8 minutos
  16. 16
    Getters y setters o atributos públicos en Java, ¿qué es mejor?
    9 minutos
  17. 17
    El String[] args del método main de Java
    8 minutos
  18. 18
    Introducción a clases anónimas en Java
    6 minutos
  19. 19
    Introducción a enum en Java
    6 minutos