JavaRush /Blogue Java /Random-PT /Classes anônimas em Java

Classes anônimas em Java

Publicado no grupo Random-PT
Olá! Na lição de hoje continuaremos a examinar o tópico das classes aninhadas. É a vez do último grupo - classes internas anônimas em Java. Voltemos ao nosso diagrama: Aulas anônimas - 2assim como as classes locais de que falamos na última aula, as classes anônimas são um subconjunto das classes internas. Eles também têm várias semelhanças e diferenças entre eles. Mas primeiro, vamos descobrir: por que eles são realmente chamados de “anônimos”? Para fazer isso, vejamos um exemplo simples. Imagine que temos um programa principal que está constantemente rodando e fazendo alguma coisa. Queremos criar um sistema de monitoramento deste programa composto por vários módulos. Um módulo monitorará os indicadores gerais de desempenho e manterá um log, o segundo registrará e registrará erros no log de erros, o terceiro monitorará atividades suspeitas: por exemplo, tentativas de acesso não autorizado e outras coisas relacionadas à segurança. Como todos os três módulos devem essencialmente iniciar no início do programa e rodar em segundo plano, é uma boa ideia criar uma interface comum para eles:
public interface MonitoringSystem {

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

@Override
   public void startMonitoring() {
       System.out.println("Monitoring of general indicators has started!");
   }
}


public class ErrorMonitoringModule implements MonitoringSystem {

   @Override
   public void startMonitoring() {
       System.out.println("Bug Tracking Monitoring Started!");
   }
}


public class SecurityModule implements MonitoringSystem {

   @Override
   public void startMonitoring() {
       System.out.println("Security monitoring started!");
   }
}
Parece que tudo está em ordem. Temos um sistema bastante claro de vários módulos. Cada um deles tem seu próprio comportamento. Se precisarmos de novos módulos, podemos adicioná-los, pois temos uma interface bastante fácil de implementar. Mas vamos pensar em como funcionará o nosso sistema de monitoramento. Aulas anônimas - 3Essencialmente, devemos apenas criar 3 objetos - GeneralIndicatorsMonitoringModule, ErrorMonitoringModule, SecurityModule- e chamar um método startMonitoring()em cada um deles. Ou seja, tudo que você precisa fazer é criar 3 objetos e chamar 1 método neles.
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();
   }
}
Saída do console:

Мониторинг общих показателей стартовал!
Мониторинг отслеживания ошибок стартовал!
Мониторинг безопасности стартовал!
E para um trabalho tão pequeno, escrevemos um sistema completo: 3 classes e uma interface! E tudo isso por causa de 6 linhas de código. Por outro lado, quais são as nossas opções? Sim, não é muito legal termos escrito classes tão “descartáveis”. Mas como podemos consertar isso? É aqui que as classes internas anônimas vêm em nosso auxílio ! Aqui está como eles se parecem em nosso caso:
public class Main {

   public static void main(String[] args) {

       MonitoringSystem generalModule = new MonitoringSystem() {
           @Override
           public void startMonitoring() {
               System.out.println("Monitoring of general indicators has started!");
           }
       };



           MonitoringSystem errorModule = new MonitoringSystem() {
           @Override
           public void startMonitoring() {
               System.out.println("Bug Tracking Monitoring Started!");
           }
       };

       MonitoringSystem securityModule = new MonitoringSystem() {
           @Override
           public void startMonitoring() {
               System.out.println("Security monitoring started!");
           }
       };

       generalModule.startMonitoring();
       errorModule.startMonitoring();
       securityModule.startMonitoring();
   }
}
Vamos descobrir o que está acontecendo aqui! Parece que estamos criando um objeto de interface:
MonitoringSystem generalModule = new MonitoringSystem() {

@Override
   public void startMonitoring() {
       System.out.println("Monitoring of general indicators has started!");
   }
};
Mas já sabemos há muito tempo que é impossível criar objetos de interface! Isso mesmo, é impossível. Na verdade, não fazemos isso. No momento em que escrevemos:
MonitoringSystem generalModule = new MonitoringSystem() {

};
Dentro da máquina Java acontece o seguinte:
  1. É criada uma classe Java sem nome que implementa o MonitoringSystem.
  2. O compilador, vendo tal classe, exige que você implemente todos os métodos de interface MonitoringSystem(fizemos isso 3 vezes).
  3. Um objeto desta classe é criado. Preste atenção ao código:
MonitoringSystem generalModule = new MonitoringSystem() {

};
Há um ponto e vírgula no final! Ela está ali por um motivo. Declaramos simultaneamente uma classe (por meio de chaves) e criamos seu objeto usando (); Cada um de nossos três objetos substituiu um método startMonitoring()à sua própria maneira. No final, simplesmente chamamos este método em cada um deles:
generalModule.startMonitoring();
errorModule.startMonitoring();
securityModule.startMonitoring();
Saída do console:

Мониторинг общих показателей стартовал!
Мониторинг отслеживания ошибок стартовал!
Мониторинг безопасности стартовал!
Isso é tudo! Concluímos nossa tarefa: criamos três objetos MonitoringSystem, redefinimos-os de três maneiras diferentes e chamamos-nos três vezes. Todos os três módulos foram iniciados e funcionando com sucesso. Ao mesmo tempo, a estrutura do nosso programa ficou muito mais simples! GeneralIndicatorsMonitoringModuleAfinal , as aulas ErrorMonitoringModuleagora podem SecurityModuleser totalmente removidas do programa! Simplesmente não precisamos deles - conseguimos muito bem sem eles. Se cada uma de nossas classes de módulos anônimos precisar de algum comportamento diferente, seus próprios métodos específicos que os outros não possuem, podemos facilmente adicioná-los:
MonitoringSystem generalModule = new MonitoringSystem() {

   @Override
   public void startMonitoring() {
       System.out.println("Monitoring of general indicators has started!");
   }

   public void someSpecificMethod() {

       System.out.println("Specific method for first module only");
   }
};
A documentação da Oracle tem uma boa recomendação : "Use classes anônimas se precisar de uma classe local para uso único." Uma classe anônima é uma classe interna completa. Portanto, ele tem acesso a variáveis ​​de classe externas, incluindo estáticas e 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("Bug Tracking Monitoring Started!");
           }

           public int getCurrentErrorsCount() {

               return currentErrorsCount;
           }
       };
   }
}
Eles têm algo em comum com as classes locais: são visíveis apenas dentro do método no qual estão definidos. No exemplo acima, qualquer tentativa de acessar o objeto errorModulefora do método main()falhará. E mais uma limitação importante que as classes anônimas herdaram de seus “ancestrais” - classes internas: uma classe anônima não pode conter variáveis ​​​​e métodos estáticos . Se tentarmos tornar getCurrentErrorsCount()estático o método do exemplo acima, o compilador gerará um erro:
//error! Inner classes cannot have static declarations
public static int getCurrentErrorsCount() {

   return currentErrorsCount;
}
Obtemos o mesmo resultado se tentarmos declarar uma variável estática:
MonitoringSystem errorModule = new MonitoringSystem() {

   //error! Inner classes cannot have static declarations!
   static int staticInt = 10;

   @Override
   public void startMonitoring() {
       System.out.println("Bug Tracking Monitoring Started!");
   }

};
Por fim, posso recomendar um excelente vídeo sobre o tema aulas anônimas, onde este tema é explicado da forma mais simples e clara possível :)
E nossa lição de hoje chegou ao fim! E embora tenhamos abordado o último grupo de classes aninhadas, ainda não terminamos este tópico. O que estudaremos a seguir sobre classes aninhadas? Você definitivamente descobrirá em breve! :)
Comentários
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION