CodeGym /Java Blog /Willekeurig /Anonieme lessen
John Squirrels
Niveau 41
San Francisco

Anonieme lessen

Gepubliceerd in de groep Willekeurig
Hoi! In de les van vandaag gaan we verder met het onderzoeken van geneste klassen. Nu is het tijd voor de laatste groep: anonieme innerlijke lessen. Laten we terugkeren naar ons diagram: Anonieme lessen - 2Net als de lokale lessen waar we het in de vorige les over hadden, zijn anonieme lessen een soort innerlijke klas... Ze hebben ook verschillende overeenkomsten en verschillen. Maar laten we er eerst in duiken: waarom worden ze precies "anoniem" genoemd? Overweeg een eenvoudig voorbeeld om dit te beantwoorden. Stel je voor dat we een basisprogramma hebben dat constant draait en iets doet. Voor dit programma willen we een monitoringsysteem maken, opgebouwd uit meerdere modules. Eén module volgt algemene prestatie-indicatoren en houdt een logboek bij. De tweede registreert en registreert fouten in een foutenlogboek. De derde houdt verdachte activiteiten bij: bijvoorbeeld ongeautoriseerde toegangspogingen en andere beveiligingsgerelateerde zaken. Omdat alle drie de modules in wezen gewoon aan het begin van het programma moeten beginnen en op de achtergrond moeten worden uitgevoerd,

public interface MonitoringSystem {
  
   public void startMonitoring();
}
3 concrete klassen zullen het implementeren:

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!");
   }
}
Het lijkt erop dat alles in orde is. We hebben een vrij samenhangend systeem dat bestaat uit verschillende modules. Elk van hen heeft zijn eigen gedrag. Als we nieuwe modules nodig hebben, kunnen we die toevoegen, omdat we een interface hebben die vrij eenvoudig te implementeren is. Maar laten we eens nadenken over hoe ons monitoringsysteem zal werken. Anonieme lessen - 3Kortom, we hoeven alleen maar 3 objecten te maken - GeneralIndicatorMonitoringModule, ErrorMonitoringModule, SecurityModule- en de startMonitoring()methode op elk ervan aan te roepen. Dat wil zeggen, we hoeven alleen maar 3 objecten te maken en er 1 methode op aan te roepen.

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();
   }
}
Console-uitvoer:

Starting to monitor general indicators! 
Starting to monitor errors! 
Starting to monitor security!
En met zo weinig werk hebben we het hele systeem geschreven: 3 klassen en één interface! En dit alles om 6 regels code te bereiken. Aan de andere kant, wat zijn onze opties? Nou, het is niet erg cool dat we deze "eenmalige" lessen hebben geschreven. Maar hoe kunnen we dit oplossen? Hier komen anonieme innerlijke klassen ons te hulp! Zo zien ze er in ons geval uit:

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();
   }
}
Laten we uitzoeken wat er aan de hand is! Het lijkt erop dat we een interface-object maken:

MonitoringSystem generalModule = new MonitoringSystem() {
   
@Override
   public void startMonitoring() {
       System.out.println("Starting to monitor general indicators!");
   }
};
Maar we weten al lang dat we geen interface-objecten kunnen maken! En zo is het - het is onmogelijk. Dat is in feite niet wat we doen. Als we schrijven:

MonitoringSystem generalModule = new MonitoringSystem() {
   
};
het volgende gebeurt binnen de Java-machine:
  1. Er wordt een naamloze Java-klasse gemaakt die de MonitoringSysteminterface implementeert.
  2. Wanneer de compiler zo'n klasse ziet, moet je alle methoden van de interface implementeren MonitoringSystem(we hebben dit 3 keer gedaan).
  3. Er wordt één object van deze klasse gemaakt. Let op de code:

MonitoringSystem generalModule = new MonitoringSystem() {
   
};
Er staat een puntkomma aan het einde! Het is er met een reden. We declareren tegelijkertijd de klasse (met accolades) en maken er een instantie van (met ();). Elk van onze drie objecten heft de startMonitoring()methode op zijn eigen manier op. Ten slotte noemen we deze methode gewoon op elk van hen:

generalModule.startMonitoring();
errorModule.startMonitoring();
securityModule.startMonitoring();
Console-uitvoer:

Starting to monitor general indicators! 
Starting to monitor errors! 
Starting to monitor security!
Dat is het! We hebben ons doel bereikt: we hebben drie MonitoringSystemobjecten gemaakt, een methode op drie verschillende manieren overschreven en drie keer aangeroepen. Alle drie de modules zijn succesvol aangeroepen en draaien. Tegelijkertijd is de structuur van ons programma veel eenvoudiger geworden! GeneralIndicatorMonitoringModuleDe lessen , ErrorMonitoringModule, en SecurityModulekunnen nu immers helemaal uit het programma gehaald worden! We hebben ze gewoon niet nodig - we hebben geweldig werk geleverd zonder hen. Als elk van onze anonieme klassen een ander gedrag nodig heeft, bijvoorbeeld zijn eigen specifieke methoden die de anderen niet hebben, kunnen we die eenvoudig toevoegen:

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");
   }
};
De Oracle-documentatie geeft een goede aanbeveling : "Gebruik [anonieme klassen] als u een lokale klasse maar één keer hoeft te gebruiken." Een anonieme klas is een volwaardige innerlijke klas. Dienovereenkomstig heeft het toegang tot de variabelen van de externe klasse, inclusief statische en privévariabelen:

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;
           }
       };
   }
}
Ze hebben iets gemeen met lokale klassen: ze zijn alleen zichtbaar binnen de methode waarin ze zijn gedeclareerd. In het bovenstaande voorbeeld mislukken alle pogingen om toegang te krijgen tot het errorModuleobject buiten de methode om. main()En er is nog een belangrijke beperking die anonieme klassen erven van hun "voorouders" (innerlijke klassen): een anonieme klasse kan geen statische variabelen en methoden bevatten . Als we in het bovenstaande voorbeeld proberen de getCurrentErrorCount()methode statisch te maken, genereert de compiler een fout:

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

   return currentErrorCount;
}
We krijgen hetzelfde resultaat als we proberen een statische variabele te declareren:

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!");
   }

};
En onze les van vandaag is ten einde! Maar ook al hebben we de laatste groep geneste klassen onderzocht, we zijn nog niet klaar met dit onderwerp. Wat gaan we nog meer leren over geneste klassen? Daar kom je vast snel achter! :)
Opmerkingen
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION