Klasy wewnętrzne i wewnętrzne lokalne i zagnieżdżone

Klasy wewnętrzne w przeciwieństwie do „zwykłych” klas javy mogą być prywatne i niewodoczne dla użytkownika(modyfikator dostępu private), protected ale również final, abstractczy public.

Wykorzystywane są głównie wtedy, gdy chcemy w niej mieć dostęp do klasy otaczającej bez konieczności tworzenia i przekazywania jej instancji lub gdy chcemy ją wykorzystać tylko w celach pomocniczych i nie ma sensu jej wydzielać tak, aby inni również mogli z niej korzystać(np. do zaimplementowania zbioru usług wykorzystywanych tylko przez klasę, w której ją zadeklarowano).

public class Samochod {
    private Silnik silnik;
     
    public Samochod() {
        silnik = new Silnik("Fiat");
        System.out.println("Utworzono samochód z silnikiem " + silnik.typSilnika);
    }
     
     public class Silnik {
         
        private String typSilnika;
		
        public Silnik(String type) {
            typSilnika = type;
        }  
    }
}

Jedną z zalet stworzenia klasy Silnik wewnątrz klasy Samochod jest to, że mamy dostęp do wszystkich pól klasy nadrzędnej, nawet jeśli nie udostępnia ona gettera i są one prywatne. Działa to także w drugą stronę: z klasy Samochod możemy odwoływać się do pól prywatnych klasy Silnik.
Tworzenie instancji klasy wewnętrznej:
Samochod.Silnik silnik = new Samochod().new Silnik(„Fiat”);
Jest to jednak rzadko używana konstrukcja.

Słowo kluczowe this w klasie wewnętrznej
Działanie tego słowa w klasie wewnętrznej różni się nieco od wykorzystania go w zwykłych klasach(służyło tam do odwoływania się do przesłoniętych przez argumenty metod, czy konstruktorów pól klasy).
Poprzez słówko this odwołujemy się do pól klasy wewnętrznej. By odwołać się do pola klasy zewnętrznej należy słówko this poprzedzić nazwą klasy (KlasaZewnetrzna.this).

public class Samochod {
    private int paliwo;
     
    private class Silnik {
        int paliwo;
         
        void spalajPaliwo() {
            //pole klasy wewnętrznej - Silnik
            this.paliwo = 5;
             
            //pole klasy otaczającej - Samochod
            Samochod.this.paliwo = 5;
        }
    }
}

Klasy wewnętrzne lokalne

Klasy wewnętrzne w javie można tworzyć również w metodach. Są to wtedy klasy wewnętrzne lokalne. Mająone dużo więcej ograniczeń:
– nie mogą posiadać specyfikatorów dostępu
– nie mogą byćstatyczne
– mogą być abstrakcyjne albo finalne
– mogą korzystać z pól klasy zewnętrznej, ale jeśli korzystają ze zmiennych lokalnych metody to zmienne te muszą być oznaczone jako finalne(od javy 8 możliwe jest także stosowanie zmiennych efektywnie finalnych).

public class Zewnetrzna {
    private int x;
     
    public void zrobCos() {
        int localVar = 5;
         
        class Wewnetrzna {
            public void wewnetrznaMetoda() {
                x = 5;
                System.out.println(localVar);
            }
        }
    }
}

Klasa „Wewnetrzna” została stworzona wewnątrz metody zrobCos. Możemy z metody w jej wnętrzu odwoływać się do pola x klasy opakowującej, możemy też wyświetlać wartość localVar, jednak tylko pod warunkiem, że nie zmienimy wartości tej zmiennej w dalszej części kodu.

Zmienna efektywnie finalna – pomimo iż nie ma modyfikatora final, to kompilator jest w stanie stwierdzić, że faktycznie jest ona raz zainicjowana i później nie zmienia wartości.

Klasy zagnieżdżone
Klasy wewnętrzne w odróżnieniu od klasycznych klas mogą być oznaczane jako statyczne – nazywać je wtedy będziemy klasami zagnieżdżonymi.
Mają one dostęp jedynie do statycznych pól klasy otaczającej oraz jeśli klasa posiada element statyczny to sama również musi być oznaczona jako statyczna.

public class Samochod {
     
    public static class Silnik {
        int paliwo;
         
        void spalPaliwo() {
            this.paliwol = 5;
        }
    }
}

Tworzenie obiektu:

Samochod.Silnik silnik = new Samochod.Silnik();

Inicjalizowanie obiektu klasy zagnieżdżonej nie wymaga tworzenia instancji klasy zewnętrznej.

Dodaj komentarz

Twój adres email nie zostanie opublikowany. Pola, których wypełnienie jest wymagane, są oznaczone symbolem *