JavaRush /Blog Java /Random-ES /Clases anónimas en Java

Clases anónimas en Java

Publicado en el grupo Random-ES
¡Hola! En la lección de hoy continuaremos analizando el tema de las clases anidadas. Es el turno del último grupo: clases internas anónimas en Java. Volvamos a nuestro diagrama: Clases anónimas - 2al igual que las clases locales de las que hablamos en la última lección, las clases anónimas son un subconjunto de clases internas. También tienen varias similitudes y diferencias entre ellos. Pero primero, averigüémoslo: ¿por qué en realidad se les llama “anónimos”? Para hacer esto, veamos un ejemplo simple. Imaginemos que tenemos un programa principal que está constantemente ejecutándose y haciendo algo. Queremos crear un sistema de seguimiento para este programa que consta de varios módulos. Un módulo monitoreará los indicadores generales de rendimiento y mantendrá un registro, el segundo registrará y registrará los errores en el registro de errores, el tercero monitoreará la actividad sospechosa: por ejemplo, intentos de acceso no autorizados y otras cosas relacionadas con la seguridad. Dado que los tres módulos básicamente deberían comenzar al principio del programa y ejecutarse en segundo plano, es una buena idea crear una interfaz común para ellos:
public interface MonitoringSystem {

   public void startMonitoring();
}
Será implementado por 3 clases específicas:
public class GeneralIndicatorsMonitoringModule implements MonitoringSystem {

@Override
   public void startMonitoring() {
       System.out.println("¡Comenzó el seguimiento de los indicadores generales!");
   }
}


public class ErrorMonitoringModule implements MonitoringSystem {

   @Override
   public void startMonitoring() {
       System.out.println("¡Comenzó el seguimiento de errores!");
   }
}


public class SecurityModule implements MonitoringSystem {

   @Override
   public void startMonitoring() {
       System.out.println("¡Comenzó el monitoreo de seguridad!");
   }
}
Parecería que todo está en orden. Tenemos un sistema bastante claro de varios módulos. Cada uno de ellos tiene su propio comportamiento. Si necesitamos nuevos módulos, podemos agregarlos, porque tenemos una interfaz bastante fácil de implementar. Pero pensemos en cómo funcionará nuestro sistema de seguimiento. Clases anónimas - 3Esencialmente, deberíamos crear 3 objetos ( GeneralIndicatorsMonitoringModule,, ErrorMonitoringModule) SecurityModuley llamar a un método startMonitoring()en cada uno de ellos. Es decir, todo lo que necesitas hacer es crear 3 objetos y llamar a 1 método en ellos.
public class Main {

   public static void main(String[] args) {

       GeneralIndicatorsMonitoringModule generalModule = new GeneralIndicatorsMonitoringModule();
       ErrorMonitoringModule errorModule = new ErrorMonitoringModule();
       SecurityModule securityModule = new SecurityModule();

       generalModule.startMonitoring();
       errorModule.startMonitoring();
       securityModule.startMonitoring();
   }
}
Salida de consola:

Мониторинг общих показателей стартовал!
Мониторинг отслеживания ошибок стартовал!
Мониторинг безопасности стартовал!
Y para un trabajo tan pequeño, escribimos un sistema completo: ¡3 clases y una interfaz! Y todo esto por 6 líneas de código. Por otro lado, ¿cuáles son nuestras opciones? Sí, no es muy bueno que hayamos escrito clases tan "desechables". Pero ¿cómo podemos solucionar esto? ¡Aquí es donde las clases internas anónimas vienen en nuestra ayuda ! Así es como se ven en nuestro caso:
public class Main {

   public static void main(String[] args) {

       MonitoringSystem generalModule = new MonitoringSystem() {
           @Override
           public void startMonitoring() {
               System.out.println("¡Comenzó el seguimiento de los indicadores generales!");
           }
       };



           MonitoringSystem errorModule = new MonitoringSystem() {
           @Override
           public void startMonitoring() {
               System.out.println("¡Comenzó el seguimiento de errores!");
           }
       };

       MonitoringSystem securityModule = new MonitoringSystem() {
           @Override
           public void startMonitoring() {
               System.out.println("¡Comenzó el monitoreo de seguridad!");
           }
       };

       generalModule.startMonitoring();
       errorModule.startMonitoring();
       securityModule.startMonitoring();
   }
}
¡Averigüemos qué está pasando aquí! Parece que estamos creando un objeto de interfaz:
MonitoringSystem generalModule = new MonitoringSystem() {

@Override
   public void startMonitoring() {
       System.out.println("¡Comenzó el seguimiento de los indicadores generales!");
   }
};
¡Pero sabemos desde hace mucho tiempo que es imposible crear objetos de interfaz! Así es, es imposible. De hecho, no hacemos eso. En el momento en que escribimos:
MonitoringSystem generalModule = new MonitoringSystem() {

};
Dentro de la máquina Java sucede lo siguiente:
  1. Se crea una clase Java sin nombre que implementa MonitoringSystem.
  2. El compilador, al ver una clase de este tipo, requiere que implemente todos los métodos de la interfaz MonitoringSystem(lo hicimos 3 veces).
  3. Se crea un objeto de esta clase. Presta atención al código:
MonitoringSystem generalModule = new MonitoringSystem() {

};
¡Hay un punto y coma al final! Ella está ahí parada por una razón. Declaramos simultáneamente una clase (mediante llaves) y creamos su objeto usando (); Cada uno de nuestros tres objetos ha anulado un método startMonitoring()a su manera. Al final simplemente llamamos a este método en cada uno de ellos:
generalModule.startMonitoring();
errorModule.startMonitoring();
securityModule.startMonitoring();
Salida de consola:

Мониторинг общих показателей стартовал!
Мониторинг отслеживания ошибок стартовал!
Мониторинг безопасности стартовал!
¡Eso es todo! Hemos completado nuestra tarea: hemos creado tres objetos MonitoringSystem, los redefinimos de tres maneras diferentes y los llamamos tres veces. Los tres módulos se han iniciado y funcionan correctamente. ¡Al mismo tiempo, la estructura de nuestro programa se ha vuelto mucho más simple! GeneralIndicatorsMonitoringModuleDespués de todo , ¡ ErrorMonitoringModuleahora las clases SecurityModulese pueden eliminar del programa por completo! Simplemente no los necesitamos; nos las arreglamos muy bien sin ellos. Si cada una de nuestras clases de módulos anónimos necesita algún comportamiento diferente, sus propios métodos específicos que los demás no tienen, podemos agregarlos fácilmente:
MonitoringSystem generalModule = new MonitoringSystem() {

   @Override
   public void startMonitoring() {
       System.out.println("¡Comenzó el seguimiento de los indicadores generales!");
   }

   public void someSpecificMethod() {

       System.out.println("Método específico solo para el primer módulo");
   }
};
La documentación de Oracle tiene una buena recomendación : "Utilice clases anónimas si necesita una clase local para un uso único". Una clase anónima es una clase interna de pleno derecho. Por lo tanto, tiene acceso a variables de clase externa, incluidas las estáticas y privadas:
public class Main {

   private static int currentErrorsCount = 23;

   public static void main(String[] args) {

       MonitoringSystem errorModule = new MonitoringSystem() {

           @Override
           public void startMonitoring() {
               System.out.println("¡Comenzó el seguimiento de errores!");
           }

           public int getCurrentErrorsCount() {

               return currentErrorsCount;
           }
       };
   }
}
Tienen algo en común con las clases locales: son visibles sólo dentro del método en el que están definidas. En el ejemplo anterior, cualquier intento de acceder al objeto errorModulefuera del método main()fallará. Y una limitación más importante que las clases anónimas heredaron de sus "antepasados": las clases internas: una clase anónima no puede contener variables y métodos estáticos . Si intentamos hacer que el método getCurrentErrorsCount()del ejemplo anterior sea estático, el compilador arrojará un error:
//¡error! Las clases internas no pueden tener declaraciones estáticas.
public static int getCurrentErrorsCount() {

   return currentErrorsCount;
}
Obtenemos el mismo resultado si intentamos declarar una variable estática:
MonitoringSystem errorModule = new MonitoringSystem() {

   //¡error! ¡Las clases internas no pueden tener declaraciones estáticas!
   static int staticInt = 10;

   @Override
   public void startMonitoring() {
       System.out.println("¡Comenzó el seguimiento de errores!");
   }

};
Por último, puedo recomendaros un excelente vídeo sobre el tema de las clases anónimas, donde se explica este tema de la forma más sencilla y clara posible :)
¡Y nuestra lección de hoy ha llegado a su fin! Y aunque hemos cubierto el último grupo de clases anidadas, aún no hemos terminado con este tema. ¿Qué estudiaremos a continuación sobre las clases anidadas? ¡Definitivamente lo descubrirás pronto! :)
Comentarios
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION