Sobes.tech
Middle

Jakie rodzaje klas zagnieżdżonych istnieją?

sobes.tech AI

Odpowiedź od AI

Zagnieżdżone klasy (Nested Classes) w Javie dzielą się na dwa główne typy:

  1. Statyczne klasy zagnieżdżone (Static Nested Classes)

    • Oznaczone modyfikatorem static.
    • Zachowują się jak zwykłe statyczne członkowie klasy kontenera.
    • Mogą uzyskać dostęp do statycznych członków klasy zewnętrznej (nawet jeśli są prywatne).
    • Nie mają bezpośredniego dostępu do nie-statycznych członków klasy zewnętrznej.
    • Tworzone bez instancji klasy zewnętrznej: OuterClass.StaticNestedClass nestedObject = new OuterClass.StaticNestedClass();.
  2. Klasy wewnętrzne (Inner Classes)

    Klasy wewnętrzne nie są oznaczone static i są powiązane z instancją klasy zewnętrznej. Dzielą się na:

    • Klasy członkowskie (Member Inner Classes)

      • Deklarowane na poziomie członka klasy kontenera, ale poza jej metodami.
      • Mają dostęp do wszystkich członków klasy zewnętrznej, w tym prywatnych.
      • Wymagają instancji klasy zewnętrznej do utworzenia własnej instancji: OuterClass outerObject = new OuterClass(); OuterClass.MemberInnerClass innerObject = outerObject.new MemberInnerClass();.
    • Klasy lokalne (Local Classes)

      • Tworzone wewnątrz metod, konstruktorów lub bloków inicjalizacyjnych.
      • Zakres ich widoczności jest ograniczony do bloku, w którym są zadeklarowane.
      • Nie można ich deklarować z modyfikatorami dostępu (public, private, protected).
      • Mogą odwoływać się do lokalnych zmiennych finalnych lub efektywnie finalnych z zewnętrznego bloku.
      • Nie mogą być używane poza blokiem, w którym są zdefiniowane.
    • Klasy anonimowe (Anonymous Classes)

      • W istocie są to anonimowe klasy lokalne.
      • Deklaruje się je i instancjonuje jednocześnie.
      • Używa się ich do implementacji klasy abstrakcyjnej lub interfejsu "na żywo".
      • Podobnie jak klasy lokalne, mają dostęp do lokalnych zmiennych finalnych lub efektywnie finalnych z zewnętrznego bloku.

Przykład struktury:

class OuterClass {
    private int outerField;
    private static int staticOuterField;

    // Statyczna klasa zagnieżdżona
    static class StaticNestedClass {
        void accessOuter() {
            // Może odwołać się do statycznych członków klasy zewnętrznej
            int value = staticOuterField;
            // Nie może odwołać się do nie-statycznych członków
            // int value2 = outerField; // Błąd kompilacji
        }
    }

    // Klasa członkowska (klasa wewnętrzna)
    class MemberInnerClass {
        void accessOuter() {
            // Może odwołać się do wszystkich członków klasy zewnętrznej
            int value1 = outerField;
            int value2 = staticOuterField;
        }
    }

    void methodWithLocalAndAnonymous() {
        final int localVar = 10; // final lub efektywnie final

        // Klasa lokalna
        class LocalClass {
            void accessOuter() {
                // Może odwołać się do członków klasy zewnętrznej i lokalnych finalnych/efektywnie finalnych zmiennych
                int value1 = outerField;
                int value2 = staticOuterField;
                int localValue = localVar;
            }
        }

        LocalClass localObj = new LocalClass();
        localObj.accessOuter();

        // Klasa anonimowa (implementująca Runnable)
        Runnable anonymousRunnable = new Runnable() {
            @Override
            public void run() {
                // Może odwołać się do członków klasy zewnętrznej i lokalnych finalnych/efektywnie finalnych zmiennych
                int value1 = outerField;
                int value2 = staticOuterField;
                int localValue = localVar;
                System.out.println("Uruchomione z lokalną zmienną: " + localValue);
            }
        };

        anonymousRunnable.run();
    }
}