JavaRush /Java Blog /Random-IT /Classi anonime in Java

Classi anonime in Java

Pubblicato nel gruppo Random-IT
Ciao! Nella lezione di oggi continueremo ad affrontare l'argomento delle classi nidificate. È il turno dell'ultimo gruppo: classi interne anonime in Java. Torniamo al nostro diagramma: Classi anonime - 2come le classi locali di cui abbiamo parlato nell'ultima lezione, le classi anonime sono un sottoinsieme delle classi interne. Hanno anche molte somiglianze e differenze tra loro. Ma prima cerchiamo di capirlo: perché in realtà si chiamano “anonimi”? Per fare ciò, diamo un'occhiata a un semplice esempio. Immagina di avere un programma principale che è costantemente in esecuzione e fa qualcosa. Vogliamo creare un sistema di monitoraggio per questo programma composto da diversi moduli. Un modulo monitorerà gli indicatori generali delle prestazioni e manterrà un registro, il secondo registrerà e registrerà gli errori nel registro degli errori, il terzo monitorerà le attività sospette: ad esempio tentativi di accesso non autorizzati e altri elementi relativi alla sicurezza. Poiché tutti e tre i moduli dovrebbero essenzialmente avviarsi all'inizio del programma ed essere eseguiti in background, è una buona idea creare per loro un'interfaccia comune:
public interface MonitoringSystem {

   public void startMonitoring();
}
Verrà implementato da 3 classi specifiche:
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!");
   }
}
Sembrerebbe che tutto sia in ordine. Abbiamo un sistema abbastanza chiaro di diversi moduli. Ognuno di loro ha il suo comportamento. Se abbiamo bisogno di nuovi moduli, possiamo aggiungerli, perché abbiamo un'interfaccia abbastanza semplice da implementare. Ma pensiamo a come funzionerà il nostro sistema di monitoraggio. Classi anonime - 3Essenzialmente, dovremmo semplicemente creare 3 oggetti - GeneralIndicatorsMonitoringModule, ErrorMonitoringModule, SecurityModule- e chiamare un metodo startMonitoring()su ciascuno di essi. Cioè, tutto ciò che devi fare è creare 3 oggetti e chiamare 1 metodo su di essi.
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();
   }
}
Uscita console:

Мониторинг общих показателей стартовал!
Мониторинг отслеживания ошибок стартовал!
Мониторинг безопасности стартовал!
E per un lavoro così piccolo abbiamo scritto un intero sistema: 3 classi e un'unica interfaccia! E tutto questo per il bene di 6 righe di codice. D’altra parte, quali sono le nostre opzioni? Sì, non è molto bello che abbiamo scritto classi così "usa e getta". Ma come possiamo risolvere questo problema? È qui che le classi interiori anonime vengono in nostro aiuto ! Ecco come appaiono nel nostro 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();
   }
}
Scopriamo cosa sta succedendo qui! Sembra che stiamo creando un oggetto interfaccia:
MonitoringSystem generalModule = new MonitoringSystem() {

@Override
   public void startMonitoring() {
       System.out.println("Monitoring of general indicators has started!");
   }
};
Ma sappiamo da tempo che è impossibile creare oggetti interfaccia! Esatto, è impossibile. In effetti, non lo facciamo. Nel momento in cui scriviamo:
MonitoringSystem generalModule = new MonitoringSystem() {

};
All'interno della macchina Java accade quanto segue:
  1. Viene creata una classe Java senza nome che implementa MonitoringSystem.
  2. Il compilatore, vedendo una classe del genere, richiede di implementare tutti i metodi dell'interfaccia MonitoringSystem(lo abbiamo fatto 3 volte).
  3. Viene creato un oggetto di questa classe. Attenzione al codice:
MonitoringSystem generalModule = new MonitoringSystem() {

};
Alla fine c'è un punto e virgola! Lei è lì per un motivo. Dichiariamo simultaneamente una classe (tramite parentesi graffe) e creiamo il suo oggetto utilizzando (); Ciascuno dei nostri tre oggetti ha sovrascritto un metodo startMonitoring()a modo suo. Alla fine chiamiamo semplicemente questo metodo su ciascuno di essi:
generalModule.startMonitoring();
errorModule.startMonitoring();
securityModule.startMonitoring();
Uscita console:

Мониторинг общих показателей стартовал!
Мониторинг отслеживания ошибок стартовал!
Мониторинг безопасности стартовал!
È tutto! Abbiamo completato il nostro compito: abbiamo creato tre oggetti MonitoringSystem, ridefinito in tre modi diversi e chiamato tre volte. Tutti e tre i moduli sono stati avviati e funzionanti con successo. Allo stesso tempo, la struttura del nostro programma è diventata molto più semplice! GeneralIndicatorsMonitoringModuleDopotutto , ErrorMonitoringModuleora le lezioni possono SecurityModuleessere rimosse del tutto dal programma! Semplicemente non ne abbiamo bisogno: ce la siamo cavata benissimo senza di loro. Se ciascuna delle nostre classi di moduli anonimi necessita di un comportamento diverso, di metodi specifici che gli altri non hanno, possiamo facilmente aggiungerli:
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");
   }
};
La documentazione Oracle ha una buona raccomandazione : "Utilizza classi anonime se hai bisogno di una classe locale per un utilizzo una tantum". Una classe anonima è una classe interna a tutti gli effetti. Pertanto, ha accesso alle variabili della classe esterna, comprese quelle statiche e private:
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;
           }
       };
   }
}
Hanno qualcosa in comune con le classi locali: sono visibili solo all'interno del metodo in cui sono definite. Nell'esempio precedente, qualsiasi tentativo di accedere all'oggetto errorModuleal di fuori del metodo main()fallirà. E un'altra limitazione importante che le classi anonime hanno ereditato dai loro "antenati": le classi interne: una classe anonima non può contenere variabili e metodi statici . Se proviamo a rendere getCurrentErrorsCount()statico il metodo dell'esempio precedente, il compilatore genererà un errore:
//error! Inner classes cannot have static declarations
public static int getCurrentErrorsCount() {

   return currentErrorsCount;
}
Otteniamo lo stesso risultato se proviamo a dichiarare una variabile statica:
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!");
   }

};
Infine, posso consigliarvi un ottimo video sul tema delle lezioni anonime, in cui questo argomento viene spiegato nel modo più semplice e chiaro possibile :)
E la nostra lezione di oggi è giunta al termine! E anche se abbiamo trattato l'ultimo gruppo di classi nidificate, non abbiamo ancora finito con questo argomento. Cosa studieremo dopo riguardo alle classi nidificate? Lo scoprirai sicuramente presto! :)
Commenti
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION