JavaRush /Blog Java /Random-PL /Klasy anonimowe w Javie

Klasy anonimowe w Javie

Opublikowano w grupie Random-PL
Cześć! Na dzisiejszej lekcji będziemy kontynuować temat klas zagnieżdżonych. Przyszła kolej na ostatnią grupę – anonimowe klasy wewnętrzne w Javie. Wróćmy do naszego diagramu: Zajęcia anonimowe – 2Podobnie jak klasy lokalne, o których mówiliśmy w ostatnim wykładzie, klasy anonimowe są podzbiorem klas wewnętrznych. Mają także kilka podobieństw i różnic między nimi. Ale najpierw zastanówmy się: dlaczego tak naprawdę nazywa się ich „anonimowymi”? Aby to zrobić, spójrzmy na prosty przykład. Wyobraź sobie, że mamy program główny, który stale działa i coś robi. Chcemy stworzyć system monitorowania tego programu składający się z kilku modułów. Jeden moduł będzie monitorował ogólne wskaźniki wydajności i prowadził dziennik, drugi będzie rejestrował i logował błędy w dzienniku błędów, trzeci będzie monitorował podejrzaną aktywność: na przykład próby nieautoryzowanego dostępu i inne rzeczy związane z bezpieczeństwem. Ponieważ wszystkie trzy moduły powinny w zasadzie zaczynać się od początku programu i działać w tle, dobrym pomysłem jest utworzenie dla nich wspólnego interfejsu:
public interface MonitoringSystem {

   public void startMonitoring();
}
Będzie on realizowany przez 3 konkretne klasy:
public class GeneralIndicatorsMonitoringModule implements MonitoringSystem {

@Override
   public void startMonitoring() {
       System.out.println(„Monitorowanie wskaźników ogólnych rozpoczęte!”);
   }
}


public class ErrorMonitoringModule implements MonitoringSystem {

   @Override
   public void startMonitoring() {
       System.out.println(„Rozpoczęto monitorowanie śledzenia błędów!”);
   }
}


public class SecurityModule implements MonitoringSystem {

   @Override
   public void startMonitoring() {
       System.out.println(„Monitorowanie bezpieczeństwa rozpoczęte!”);
   }
}
Wydawać by się mogło, że wszystko jest w porządku. Mamy dość przejrzysty system kilku modułów. Każdy z nich ma swoje własne zachowanie. Jeśli potrzebujemy nowych modułów, możemy je dodać, ponieważ mamy interfejs, który jest dość łatwy do wdrożenia. Zastanówmy się jednak, jak będzie działał nasz system monitorowania. Zajęcia anonimowe – 3Zasadniczo powinniśmy po prostu utworzyć 3 obiekty - GeneralIndicatorsMonitoringModule, ErrorMonitoringModule, SecurityModule- i wywołać metodę startMonitoring()na każdym z nich. Oznacza to, że wystarczy utworzyć 3 obiekty i wywołać na nich 1 metodę.
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();
   }
}
Wyjście konsoli:

Мониторинг общих показателей стартовал!
Мониторинг отслеживания ошибок стартовал!
Мониторинг безопасности стартовал!
A do tak małego zadania napisaliśmy cały system: 3 klasy i jeden interfejs! A wszystko to ze względu na 6 linijek kodu. Z drugiej strony, jakie mamy opcje? Tak, to nie jest fajne, że pisaliśmy takie „jednorazowe” zajęcia. Ale jak możemy to naprawić? Tutaj z pomocą przychodzą nam anonimowe klasy wewnętrzne ! Oto jak wyglądają w naszym przypadku:
public class Main {

   public static void main(String[] args) {

       MonitoringSystem generalModule = new MonitoringSystem() {
           @Override
           public void startMonitoring() {
               System.out.println(„Monitorowanie wskaźników ogólnych rozpoczęte!”);
           }
       };



           MonitoringSystem errorModule = new MonitoringSystem() {
           @Override
           public void startMonitoring() {
               System.out.println(„Rozpoczęto monitorowanie śledzenia błędów!”);
           }
       };

       MonitoringSystem securityModule = new MonitoringSystem() {
           @Override
           public void startMonitoring() {
               System.out.println(„Monitorowanie bezpieczeństwa rozpoczęte!”);
           }
       };

       generalModule.startMonitoring();
       errorModule.startMonitoring();
       securityModule.startMonitoring();
   }
}
Zastanówmy się, co tu się dzieje! Wygląda na to, że tworzymy obiekt interfejsu:
MonitoringSystem generalModule = new MonitoringSystem() {

@Override
   public void startMonitoring() {
       System.out.println(„Monitorowanie wskaźników ogólnych rozpoczęte!”);
   }
};
Ale już od dawna wiemy, że nie da się stworzyć obiektów interfejsu! Zgadza się, to niemożliwe. W rzeczywistości tego nie robimy. Moment, w którym piszemy:
MonitoringSystem generalModule = new MonitoringSystem() {

};
Wewnątrz maszyny Java dzieje się co następuje:
  1. Tworzona jest nienazwana klasa Java, która implementuje klasę MonitoringSystem.
  2. Kompilator widząc taką klasę wymaga zaimplementowania wszystkich metod interfejsu MonitoringSystem(robiliśmy to 3 razy).
  3. Tworzony jest jeden obiekt tej klasy. Zwróć uwagę na kod:
MonitoringSystem generalModule = new MonitoringSystem() {

};
Na końcu jest średnik! Ona stoi tam nie bez powodu. Jednocześnie deklarujemy klasę (poprzez nawiasy klamrowe) i tworzymy jej obiekt za pomocą. Każdy z naszych trzech obiektów na swój sposób (); nadpisał metodę . startMonitoring()Na koniec po prostu wywołujemy tę metodę na każdym z nich:
generalModule.startMonitoring();
errorModule.startMonitoring();
securityModule.startMonitoring();
Wyjście konsoli:

Мониторинг общих показателей стартовал!
Мониторинг отслеживания ошибок стартовал!
Мониторинг безопасности стартовал!
To wszystko! Wykonaliśmy nasze zadanie: stworzyliśmy trzy obiekty MonitoringSystem, zdefiniowaliśmy je na trzy różne sposoby i trzykrotnie wywołaliśmy. Wszystkie trzy moduły zostały pomyślnie uruchomione i działają. Jednocześnie struktura naszego programu stała się znacznie prostsza! GeneralIndicatorsMonitoringModuleW końcu zajęcia można ErrorMonitoringModuleteraz SecurityModulecałkowicie usunąć z programu! Po prostu ich nie potrzebujemy – poradziliśmy sobie bez nich. Jeśli każda z naszych anonimowych klas modułów potrzebuje innego zachowania, własnych, specyficznych metod, których nie mają inne, możemy je łatwo dodać:
MonitoringSystem generalModule = new MonitoringSystem() {

   @Override
   public void startMonitoring() {
       System.out.println(„Monitorowanie wskaźników ogólnych rozpoczęte!”);
   }

   public void someSpecificMethod() {

       System.out.println(„Określona metoda tylko dla pierwszego modułu”);
   }
};
Dokumentacja Oracle zawiera dobrą rekomendację : „Użyj klas anonimowych, jeśli potrzebujesz klasy lokalnej do jednorazowego użytku”. Klasa anonimowa jest pełnoprawną klasą wewnętrzną. Dzięki temu ma dostęp do zmiennych klas zewnętrznych, w tym statycznych i prywatnych:
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(„Rozpoczęto monitorowanie śledzenia błędów!”);
           }

           public int getCurrentErrorsCount() {

               return currentErrorsCount;
           }
       };
   }
}
Mają coś wspólnego z klasami lokalnymi: są widoczne tylko wewnątrz metody, w której są zdefiniowane. W powyższym przykładzie każda próba uzyskania dostępu do obiektu errorModulepoza metodą main()zakończy się niepowodzeniem. I jeszcze jedno ważne ograniczenie, które klasy anonimowe odziedziczyły po swoich „przodkach” – klasach wewnętrznych: klasa anonimowa nie może zawierać zmiennych i metod statycznych . Jeśli spróbujemy uczynić metodę getCurrentErrorsCount()z powyższego przykładu statyczną, kompilator zgłosi błąd:
//błąd! Klasy wewnętrzne nie mogą mieć deklaracji statycznych
public static int getCurrentErrorsCount() {

   return currentErrorsCount;
}
Ten sam wynik otrzymamy, jeśli spróbujemy zadeklarować zmienną statyczną:
MonitoringSystem errorModule = new MonitoringSystem() {

   //błąd! Klasy wewnętrzne nie mogą mieć deklaracji statycznych!
   static int staticInt = 10;

   @Override
   public void startMonitoring() {
       System.out.println(„Rozpoczęto monitorowanie śledzenia błędów!”);
   }

};
Na koniec mogę polecić Wam świetny filmik na temat zajęć anonimowych, gdzie temat ten jest wyjaśniony możliwie prosto i przejrzyście :)
I nasza dzisiejsza lekcja dobiegła końca! I choć omówiliśmy już ostatnią grupę klas zagnieżdżonych, to jeszcze nie skończyliśmy z tym tematem. Czego będziemy się dalej uczyć na temat klas zagnieżdżonych? Z pewnością przekonasz się już wkrótce! :)
Komentarze
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION