programowanieProgramista Java

Opowiedz o kluczowych cechach pracy z klasami anonimowymi i zagnieżdżonymi w Javie, a także o pułapkach ich używania.

Zdaj rozmowy kwalifikacyjne z asystentem AI Hintsage

Odpowiedź.

Klasy zagnieżdżone to klasy zdefiniowane wewnątrz innej klasy. Mogą być:

  • Static nested classes — statyczne klasy zagnieżdżone; nie mają dostępu do niestatycznych członów klasy zewnętrznej bez instancji.
  • Inner classes — niestatyczne klasy zagnieżdżone; mają dostęp do wszystkich członów klasy zewnętrznej.
  • Klasy anonimowe — wewnętrzne klasy bez nazwy, deklarowane i tworzone zazwyczaj w miejscu użycia, często przy pracy z interfejsami/klasami abstrakcyjnymi.

Przykład klasy anonimowej:

Button b = new Button(); b.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { // działanie po naciśnięciu } });

Cechy:

  • Klasy anonimowe mogą odnosić się tylko do finalnych (efektywnie finalnych) zmiennych zewnętrznego obszaru.
  • W każdej instancji wewnętrznej klasy niejawnie przechowywana jest referencja do instancji klasy zewnętrznej.
  • W zależności od typu (static/inner) mogą wystąpić wycieki pamięci lub nieoczekiwane zależności.

Pytanie z pułapką.

Czy wewnętrzna (non-static inner) klasa może zawierać metody lub zmienne statyczne?

Odpowiedź: Nie, nie może, z wyjątkiem stałych (static final). Tylko static nested class (statyczna klasa zagnieżdżona) może mieć człony statyczne.

Przykład (błąd):

class Outer { class Inner { static int x = 10; // Błąd kompilacji! } }

Poprawnie będzie tak:

class Outer { static class StaticNested { static int x = 10; // OK } }

Przykłady rzeczywistych błędów z powodu braku znajomości tematu.


Historia

W aplikacji na Androida użyto inner class jako obsługę zdarzeń. Obsługa była przechowywana w polu static i trzymała niejawne odniesienie do Activity, co spowodowało wyciek pamięci po jej zniszczeniu, a aplikacja zaczęła "przeciekać", aż do OutOfMemoryError.


Historia

W jednym z mikrousług użyto klas anonimowych, które odnosiły się do zewnętrznych zmiennych-iteracyjnych. Po refaktoryzacji zmienne przestały być efektywnie finalne, a kod przestał się kompilować — programiści długo szukali przyczyny, aż przypomnieli sobie o tym ograniczeniu.


Historia

W bibliotece użyto zmiennych statycznych wewnątrz inner class, myśląc, że to powszechna praktyka. W nowych wersjach JDK projekt przestał się kompilować, ponieważ standard stał się bardziej restrykcyjny w przestrzeganiu ograniczeń. Konieczna była pilna przeróbka architektury.