CodeGym /Java-Blog /Random-DE /Anonymer Unterricht
Autor
John Selawsky
Senior Java Developer and Tutor at LearningTree

Anonymer Unterricht

Veröffentlicht in der Gruppe Random-DE
Hallo! In der heutigen Lektion beschäftigen wir uns weiterhin mit dem Thema verschachtelter Klassen. Jetzt ist es Zeit für die letzte Gruppe: anonyme innere Klassen. Kehren wir zu unserem Diagramm zurück: Anonymer Unterricht - 2Wie die lokalen Klassen, über die wir in der letzten Lektion gesprochen haben, sind anonyme Klassen eine Art innere Klasse ... Sie weisen auch einige Gemeinsamkeiten und Unterschiede auf. Aber lassen Sie uns zunächst näher darauf eingehen: Warum genau werden sie „anonym“ genannt? Um dies zu beantworten, betrachten Sie ein einfaches Beispiel. Stellen Sie sich vor, wir hätten ein Basisprogramm, das ständig läuft und etwas tut. Wir wollen für dieses Programm ein Monitoringsystem erstellen, das aus mehreren Modulen besteht. Ein Modul verfolgt allgemeine Leistungsindikatoren und führt ein Protokoll. Beim zweiten werden Fehler in einem Fehlerprotokoll registriert und aufgezeichnet. Die dritte Funktion verfolgt verdächtige Aktivitäten: zum Beispiel unbefugte Zugriffsversuche und andere sicherheitsrelevante Dinge. Da alle drei Module im Wesentlichen einfach am Anfang des Programms starten und im Hintergrund laufen sollten,

public interface MonitoringSystem {
  
   public void startMonitoring();
}
3 konkrete Klassen werden es umsetzen:

public class GeneralIndicatorMonitoringModule implements MonitoringSystem {
   
@Override
   public void startMonitoring() {
       System.out.println("Starting to monitor general indicators!");
   }
}


public class ErrorMonitoringModule implements MonitoringSystem {

   @Override
   public void startMonitoring() {
       System.out.println("Starting to monitor errors!");
   }
}


public class SecurityModule implements MonitoringSystem {

   @Override
   public void startMonitoring() {
       System.out.println("Starting to monitor security!");
   }
}
Es scheint, dass alles in Ordnung ist. Wir haben ein ziemlich zusammenhängendes System, das aus mehreren Modulen besteht. Jeder von ihnen hat sein eigenes Verhalten. Wenn wir neue Module benötigen, können wir diese hinzufügen, da wir über eine Schnittstelle verfügen, die recht einfach zu implementieren ist. Aber denken wir darüber nach, wie unser Überwachungssystem funktionieren wird. Anonymer Unterricht - 3Im Grunde müssen wir nur drei Objekte erstellen – GeneralIndicatorMonitoringModule, ErrorMonitoringModule, SecurityModule– und startMonitoring()für jedes davon die Methode aufrufen. Das heißt, wir müssen lediglich drei Objekte erstellen und eine Methode für sie aufrufen.

public class Main {

   public static void main(String[] args) {

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

       generalModule.startMonitoring();
       errorModule.startMonitoring();
       securityModule.startMonitoring();
   }
}
Konsolenausgabe:

Starting to monitor general indicators! 
Starting to monitor errors! 
Starting to monitor security!
Und mit so wenig Arbeit haben wir das gesamte System geschrieben: 3 Klassen und eine Schnittstelle! Und das alles, um 6 Codezeilen zu erreichen. Was sind andererseits unsere Optionen? Nun, es ist nicht sehr cool, dass wir diese „einmaligen“ Kurse geschrieben haben. Aber wie können wir das beheben? Hier kommen uns anonyme innere Klassen zu Hilfe! So sehen sie in unserem Fall aus:

public class Main {

   public static void main(String[] args) {

       MonitoringSystem generalModule = new MonitoringSystem() {
           @Override
           public void startMonitoring() {
               System.out.println("Starting to monitor general indicators!");
           }
       };

       

MonitoringSystem errorModule = new MonitoringSystem() {
           @Override
           public void startMonitoring() {
               System.out.println("Starting to monitor errors!");
           }
       };

       MonitoringSystem securityModule = new MonitoringSystem() {
           @Override
           public void startMonitoring() {
               System.out.println("Starting to monitor security!");
           }
       };

       generalModule.startMonitoring();
       errorModule.startMonitoring();
       securityModule.startMonitoring();
   }
}
Lasst uns herausfinden, was los ist! Es sieht so aus, als würden wir ein Schnittstellenobjekt erstellen:

MonitoringSystem generalModule = new MonitoringSystem() {
   
@Override
   public void startMonitoring() {
       System.out.println("Starting to monitor general indicators!");
   }
};
Aber wir wissen schon lange, dass wir keine Schnittstellenobjekte erstellen können! Und so ist es – es ist unmöglich. Tatsächlich ist es nicht das, was wir tun. Wenn wir schreiben:

MonitoringSystem generalModule = new MonitoringSystem() {
   
};
Folgendes geschieht innerhalb der Java-Maschine:
  1. Es wird eine unbenannte Java-Klasse erstellt, die die Schnittstelle implementiert MonitoringSystem.
  2. Wenn der Compiler eine solche Klasse erkennt, müssen Sie alle Methoden der Schnittstelle implementieren MonitoringSystem(wir haben dies dreimal durchgeführt).
  3. Ein Objekt dieser Klasse wird erstellt. Achten Sie auf den Code:

MonitoringSystem generalModule = new MonitoringSystem() {
   
};
Am Ende steht ein Semikolon! Es gibt einen Grund dafür. Wir deklarieren gleichzeitig die Klasse (mit geschweiften Klammern) und erstellen eine Instanz davon (mit ();). Jedes unserer drei Objekte überschreibt die startMonitoring()Methode auf seine eigene Weise. Zum Schluss rufen wir einfach diese Methode für jeden von ihnen auf:

generalModule.startMonitoring();
errorModule.startMonitoring();
securityModule.startMonitoring();
Konsolenausgabe:

Starting to monitor general indicators! 
Starting to monitor errors! 
Starting to monitor security!
Das ist es! Wir haben unser Ziel erreicht: Wir haben drei MonitoringSystemObjekte erstellt, eine Methode auf drei verschiedene Arten überschrieben und sie dreimal aufgerufen. Alle drei Module wurden erfolgreich aufgerufen und laufen. Gleichzeitig ist der Aufbau unseres Programms deutlich einfacher geworden! Schließlich können die Klassen GeneralIndicatorMonitoringModule, ErrorMonitoringModuleund SecurityModulejetzt vollständig aus dem Programm entfernt werden! Wir brauchen sie einfach nicht – ohne sie haben wir einen tollen Job gemacht. Wenn jede unserer anonymen Klassen ein anderes Verhalten benötigt, z. B. eigene spezifische Methoden, die die anderen nicht haben, können wir sie einfach hinzufügen:

MonitoringSystem generalModule = new MonitoringSystem() {
  
   @Override
   public void startMonitoring() {
       System.out.println("Starting to monitor general indicators!");
   }
  
   public void someSpecificMethod() {

       System.out.println("Specific method only for the first module");
   }
};
Die Oracle-Dokumentation gibt eine gute Empfehlung : „Verwenden Sie [anonyme Klassen], wenn Sie eine lokale Klasse nur einmal verwenden müssen.“ Eine anonyme Klasse ist eine vollwertige innere Klasse. Dementsprechend hat es Zugriff auf die Variablen der externen Klasse, einschließlich statischer und privater Variablen:

public class Main {

   private static int currentErrorCount = 23;

   public static void main(String[] args) {

       MonitoringSystem errorModule = new MonitoringSystem() {
          
           @Override
           public void startMonitoring() {
               System.out.println("Starting to monitor errors!");
           }

           public int getCurrentErrorCount() {

               return currentErrorCount;
           }
       };
   }
}
Sie haben etwas mit lokalen Klassen gemeinsam: Sie sind nur innerhalb der Methode sichtbar, in der sie deklariert werden. Im obigen Beispiel schlagen alle Versuche fehl, errorModuleaußerhalb der Methode auf das Objekt zuzugreifen . main()Und es gibt noch eine weitere wichtige Einschränkung, die anonyme Klassen von ihren „Vorfahren“ (inneren Klassen) erben: Eine anonyme Klasse kann keine statischen Variablen und Methoden enthalten . Wenn wir im obigen Beispiel versuchen, die getCurrentErrorCount()Methode statisch zu machen, generiert der Compiler einen Fehler:

// Error! Inner classes cannot have static declarations
public static int getCurrentErrorCount() {

   return currentErrorCount;
}
Das gleiche Ergebnis erhalten wir, wenn wir versuchen, eine statische Variable zu deklarieren:

MonitoringSystem errorModule = new MonitoringSystem() {

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

   @Override
   public void startMonitoring() {
       System.out.println("Starting to monitor errors!");
   }

};
Und unsere heutige Lektion ist zu Ende! Aber obwohl wir die letzte Gruppe verschachtelter Klassen untersucht haben, sind wir mit diesem Thema noch nicht fertig. Was erfahren wir noch über verschachtelte Klassen? Das werden Sie bestimmt bald erfahren! :) :)
Kommentare
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION