klasy wewnętrzne w Javie

Klasa wewnętrzna znaczenie
jak sama nazwa wskazuje, Klasa wewnątrz innej klasy jest nazywana klasą wewnętrzną.
klasy wewnętrzne mają specjalną relację z klasą zawierającą, ponieważ mają dostęp do wszystkich członków klasy zewnętrznej (nawet tych private).
dzieje się tak dlatego, że Klasa wewnętrzna jest również członkiem klasy zewnętrznej, podobnie jak inne pola i metody.
ponieważ Klasa wewnętrzna jest klasą wewnątrz innej klasy, może być również określana jako klasa zagnieżdżona.
rodzaje klas wewnętrznych
Klasa wewnętrzna może być następujących typów.

  1. Normalna lub zwykła lub zagnieżdżona Klasa wewnętrzna(zwykle określana jako klasa wewnętrzna)
  2. metoda lokalna Klasa wewnętrzna.
  3. anonimowa Klasa wewnętrzna.
  4. statyczna Klasa zagnieżdżona

1. Zagnieżdżona Klasa wewnętrzna
Ta sekcja zagnieżdżi wszystkie szczegóły klasy wewnętrznej. Dla uproszczenia rozważmy następujące klasy

class Outer { private String outerField = "Outer"; class Inner { private String innerField = "Inner"; }}

tutaj Outer jest klasą zewnętrzną, a Inner jest klasą wewnętrzną, która jest zawarta wewnątrz Outer.

Tworzenie obiektu klasy wewnętrznej
Klasa wewnętrzna jest wewnątrz innej klasy. Klasa zawierająca nazywana jest klasą zewnętrzną. Tak więc Klasa wewnętrzna nie może istnieć bez klasy zewnętrznej i to samo dotyczy jej obiektu (lub instancji).
obiekt klasy wewnętrznej nie może istnieć bez obiektu klasy zewnętrznej.
oznacza to, że aby utworzyć instancję klasy wewnętrznej, musisz mieć instancję klasy zewnętrznej.
w ten sposób obiekt klasy wewnętrznej można wytworzyć poniższą metodą.

// first, create object of outer classOuter outerObject = new Outer();// create object of inner classInner innerObject = outerObject.new Inner();

Jak wynika z przykładu, aby utworzyć obiekt klasy wewnętrznej, potrzebny jest obiekt klasy zewnętrznej.
istnieje również krótka metoda tworzenia obiektu klasy wewnętrznej.

Inner innerObject = new Outer().new Inner();

ta metoda wymaga również zewnętrznego obiektu klasy.
po prostu Remember….An obiekt klasy wewnętrznej nie może zostać utworzony bez obiektu jego zawierającego (lub klasy zewnętrznej).

Tworzenie obiektu klasy wewnętrznej wewnątrz klasy zewnętrznej
poprzedni przykład zakłada, że tworzysz instancję klasy wewnętrznej gdzieś poza klasą zewnętrzną.
ale w większości przypadków obiekt klasy wewnętrznej jest wymagany tylko wewnątrz klasy zewnętrznej, ponieważ Klasa zewnętrzna korzysta z klasy wewnętrznej.
jak więc stworzyć obiekt klasy wewnętrznej z klasy zewnętrznej?
rozważ zmodyfikowaną klasę próbki poniżej.

class Outer { private String outerField = "Outer"; public void createInnerClassObject() { // create an object of inner class Inner innerObject = new Inner(); } class Inner { private String innerField = "Outer"; }}

zwróć uwagę na linię Inner innerObject = new Inner();.
wcześniej stwierdzono, że obiekt klasy wewnętrznej nie może zostać utworzony bez obiektu klasy zewnętrznej, ale robi to powyższy fragment kodu. Zdezorientowany !!!!
powyższa składnia jest poprawna, ponieważ jest zapisana wewnątrz metody zewnętrznej klasy.
kiedy ten kod jest wykonywany, istnieje już instancja klasy zewnętrznej, która uruchamia metodę.

zawsze pamiętaj, że aby utworzyć(lub uzyskać dostęp) do obiektu klasy wewnętrznej, powinna istnieć instancja klasy zewnętrznej.

do podsumowania,

  1. gdy obiekt klasy wewnętrznej jest tworzony z wewnątrz klasy zewnętrznej, można go utworzyć bezpośrednio jako Inner innerObject = new Inner();.
  2. gdy obiekt klasy wewnętrznej jest tworzony z zewnątrz klasy zewnętrznej, musi być utworzony jako Inner innerObject = new Outer().new Inner();.

gdy są drukowane obiekty klasy zewnętrznej i wewnętrznej, poniżej jest generowane wyjście:

zewnętrzna instancja klasy: zewnętrzna@659e0bfd
wewnętrzna instancja klasy : Outer$Inner@2a139a55

odwoływanie się do instancji klasy zewnętrznej, pól i metod z klasy wewnętrznej
Klasa wewnętrzna jest również członkiem jej klasy zawierającej, podobnie jak inne pola i metody.
w ten sposób może uzyskać dostęp do innych pól i metod klasy zewnętrznej w taki sam sposób, jak inne pola i metody mają bezpośredni dostęp do siebie.
to jest prawdziwe podczas uzyskiwania dostępu do zewnętrznych pól klasy i metod z klasy wewnętrznej.

ale kiedy odwołuje się do instancji klasy zewnętrznej, Istnieje różnica. Aby odwołać się do bieżącej instancji klasy, używane jest słowo kluczowe this.
w przypadku klasy wewnętrznej, użycie this wewnątrz klasy wewnętrznej odnosi się do bieżącej instancji klasy wewnętrznej, a nie do jej klasy zewnętrznej.
aby odwołać się do instancji klasy zewnętrznej z klasy wewnętrznej, musimy dodać nazwę klasy do słowa kluczowego this.

tak więc, aby odwołać się do zewnętrznej instancji klasy z klasy wewnętrznej, użyj składni Outer.this.
zobacz poniższy przykład dla zrozumienia.

class Outer { private String outerField = "Outer"; public void createInnerClassObject() { // create an object of inner class Inner innerObject = new Inner(); } class Inner { private String innerField = "Outer"; public innerClassMethod() { // access outer class field System.out.println("Outer field : " + outerField); // access inner class instance System.out.println("Inner instance : " + this); // access outer class instance System.out.println("Outer instance : " + Outer.this); } }}

wyjście

pole zewnętrzne: zewnętrzne
instancja wewnętrzna:
instancja zewnętrzna:

2. Metoda lokalna Klasa wewnętrzna
jak sama nazwa wskazuje, Klasa zdefiniowana wewnątrz metody jest lokalną klasą wewnętrzną metody.
tak, to możliwe.
możesz zdefiniować klasę wewnątrz metody, jak pokazano poniżej.

// outer classclass Outer { // outer class method public void createClass() { // class inside a method class Inner { // inner class method public void innerMethod() { System.out.println("Method local inner class"); } } // inner class ends } // method ends}

powyższy kod posiada klasę zewnętrzną zawierającą metodę.
metoda ta definiuje klasę, która znajduje się wewnątrz ciała metody, stąd nazywa się lokalną klasą wewnętrzną metody.
zauważ, że Klasa wewnętrzna ma również własną definicję metody.

Tworzenie instancji metody local Inner class
poprzedzający kod deklaruje metodę local inner class, ale nie tworzy ona żadnego obiektu klasy wewnętrznej.
teraz pojawia się pytanie, Jak utworzyć obiekt metody local Inner class.
ponieważ wewnątrz metody jest zdefiniowana lokalna Klasa wewnętrzna metody, jest ona widoczna tylko wewnątrz tej metody, a jej obiekt można również wytworzyć tylko wewnątrz tej metody.
poniższy kod wytworzy obiekt metody local Inner class i wywoła jej metodę.

// outer classpublic class Outer { // outer class method public void createClass() { // class inside a method class Inner { // inner class method public void innerMethod() { System.out.println("Method local inner class method called"); } } // inner class ends // create inner class object Inner innerObject = new Inner(); // call inner class method innerObject.innerMethod(); } // outer class method ends // Main method public static void main(String args) { // create object of outer class Outer outerObject = new Outer(); // call outer class method outerObject.createClass(); }}

gdy powyższy kod jest wykonywany, poniżej znajduje się wyjście

metoda local Inner class metoda wywołana

pokazuje to, że gdy wywołana jest metoda outer class, tworzy ona obiekt klasy wewnętrznej i wywołuje metodę klasy wewnętrznej.

metoda Local Inner Class: zwraca uwagę na polecenie
, które wytworzy obiekt metody local Inner class należy zapisać poza ciałem klasy.
tak więc linia Inner innerObject = new Inner(); powinna pojawić się po zakończeniu klasy lokalnej.

  1. metoda lokalna Klasa wewnętrzna może być utworzona tylko wewnątrz metody, w której jest zadeklarowana.
    ma to sens, ponieważ Klasa metody jest widoczna tylko wewnątrz metody, a więc jej obiekt można wytworzyć tylko wewnątrz tej metody.
  2. lokalna Klasa wewnętrzna metody nie może uzyskać dostępu do zmiennych lokalnych metody, w której jest zadeklarowana.
    jeśli potrzebuje do nich dostępu, powinny być oznaczone final.
    ma to zastosowanie przed java 8.
  3. nie można uzyskać dostępu do zmiennej lokalnej metody wewnątrz lokalnej klasy wewnętrznej metody, a następnie ponownie ją przypisać. To będzie błąd kompilatora.
    ma to zastosowanie w java 8, ponieważ wersje wcześniejsze niż java 8 nie pozwalają nawet na dostęp do zmiennej lokalnej metody wewnątrz klasy wewnętrznej.
  4. metoda lokalna Klasa wewnętrzna może uzyskać dostęp do pól i innych metod klasy, do której należy metoda zawierająca klasę wewnętrzną.
  5. metoda lokalna Klasa wewnętrzna może uzyskać dostęp do pól static i innych metod static klasy, do której należy metoda zawierająca klasę wewnętrzną tylko wtedy, gdy metoda zawierająca jest static.

3. Anonymous Inner Classes
Anonymous oznacza, którego nazwa nie jest znana. W kontekście Javy, Klasa anonimowa to taka, która nie ma nazwy.
termin Klasa anonimowa ma zastosowanie tylko do klas wewnętrznych, ponieważ klasy zewnętrzne powinny mieć nazwę.
Klasa anonimowa jest klasą wewnętrzną, ponieważ zawsze będzie zdefiniowana wewnątrz innej klasy.

typy klasy anonymous w Javie
w rzeczywistości Klasa anonymous jest implementacją już istniejącej klasy lub interfejsu, który jest napisany gdzie indziej, ale jest definiowany ponownie wewnątrz innej klasy, zgodnie z wymaganiami.
to może wydawać się mylące, ale poniższe przykłady wyjaśnią to pojęcie.

W zależności od tego, czy klasa anonymous jest implementacją klasy, czy interfejsu, może należeć do następujących dwóch kategorii

A. Podklasa klasy
zacznijmy od przykładu najpierw

// Already existing classclass Website {public void printName() {System.out.println("No website till now");}}class SearchEngine { // Notice the syntax Website w = new WebSite() { public void printName() { System.out.println("Website is codippa.com"); } };}

w powyższym przykładzie istnieje klasa o nazwie Website, która jest już utworzona.
inna klasa SearchEngine na nowo definiuje tę klasę, implementuje jej metodę i przypisuje ją do zmiennej referencyjnej, która jest tego samego typu co rzeczywista Klasa.
można również wywołać nowo zaimplementowaną metodę przy pomocy tej zmiennej referencyjnej.

pamiętaj, że nowo zaimplementowana Klasa anonimowa jest podklasą rzeczywistej klasy.
podąża za polimorfizmem i jego obiekt można przekazać wszędzie tam, gdzie oczekuje się obiektu klasy Website.
przejrzyj poniższy przykład dla ilustracji.

class Website { public void printName() { System.out.println("No website till now"); }}class SearchEngine { // Notice the syntax Website w = new WebSite() { public void printName() { System.out.println("Website is codippa.com"); } }; // Expects an instance of Website class public void getWebsite(Website web) { // call the method of Website class web.printName(); } // Main method public static void main(String args) { // create an object of this class SearchEngine obj = new SearchEngine(); // call its method and pass instance of Website class obj.getWebsite(obj.w); }}

zamiast wstępnie definiować implementację klasy Website, można ją zdefiniować tam, gdzie jest to wymagane, czyli podczas wywoływania metody getWebsite.
tak więc główną metodę można zmodyfikować jako

public static void main(String args) { SearchEngine obj = new SearchEngine(); // Notice the implementation of Website class as argument obj.getWebsite(new Website() { public void print() { System.out.println("Dynamic implementation"); } });}

powyższa implementacja nie jest przypisana do żadnej zmiennej referencyjnej, nie ma nazwy i stąd nazwa Anonymous.

nie jest konieczne, aby obie klasy znajdowały się w tym samym pliku lub pakiecie. Mogą znajdować się w dowolnym miejscu względem siebie.

B. implementator interfejsu
Klasa anonimowa może być również zdefiniowana jako implementator interfejsu.
w tym przypadku zdefiniuje implementację metod zadeklarowanych w interfejsie i może być przekazywana gdziekolwiek obiekt interfejsu jest oczekiwany.
zobacz poniższy przykład, aby to wyjaśnić.

interface WebInterface { // interface method declaration public void print();}class SearchEngine { // Notice the syntax WebInterface w = new WebInterface() { // Interface method implementation public void printName() { System.out.println("Website is codippa.com"); } }; // Expects an instance of WebInterface interface public void getWebsite(WebInterface web) { // call the method of WebInterface web.printName(); } // Main method public static void main(String args) { // create an object of this class SearchEngine obj = new SearchEngine(); // call its method and pass instance of WebInterface obj.getWebsite(obj.w); }}

jak poprzednio, implementacja interfejsu jako klasy anonimowej może być utworzona w razie potrzeby, jak pokazano poniżej.

public static void main(String args) { SearchEngine obj = new SearchEngine(); // Notice the implementation of WebInterface as argument obj.getWebsite(new WebInterface() { public void print() { System.out.println("Dynamic implementation"); } });}
zwróć uwagę na użycie słowa kluczowego new przed nazwą interfejsu. Klasa anonimowa jest jedynym miejscem, w którym jest to możliwe.

polimorfizm w klasach anonimowych
jak stwierdzono wcześniej, klasy anonimowe podążają za polimorfizmem.
ponieważ są podklasami, powinny podążać za polimorfizmem . W tej sekcji szczegółowo opisano, w jaki sposób.
rozważ poniższą klasę.

class Metal { public void printThickness() { System.out.println("Thick enough"); }}class MetalDriver { // Anonymous class definition Metal metal = new Metal() { public void printThickness() { System.out.println("Thick enough"); } // new method public boolean hasLustre() { return false; } }; public void printMetalDetail(Metal m) { // call method present in actual class definition. No problem!!! m.printThickness(); // call newly defined method in Anonymous class. Compiler Error!!! m.hasLustre(); }}

powyższy kod definiuje klasę Metal za pomocą jednej metody.
ta klasa jest ponownie zaimplementowana anonimowo w innej klasie MetalDriver, gdzie do jej definicji dodaje się nową metodę, która nie występuje w rzeczywistej klasie.

teraz, gdy ta nowa metoda jest wywoływana, kompilator skarży się na błąd

metoda hasLustre() jest niezdefiniowana dla typu Metal.

dzieje się tak, ponieważ Klasa anonymous jest podklasą, podczas gdy Referencja jest rzeczywistą klasą(która jest rodzicem).
kompilator nie może znaleźć nowej metody w klasie nadrzędnej i zgłasza błąd.

tak więc błąd ustanawia dwa fakty:
(i) klasa anonimowa jest podklasą klasy rzeczywistej, a
(ii) definicje klas anonimowych wynikają z polimorfizmu.

użycie klasy anonymous
Załóżmy, że musisz wywołać metodę, która pobiera argument typu, który jest interfejsem.
teraz ten interfejs należy do jakiejś zewnętrznej biblioteki i nie masz klasy, która implementuje ten interfejs.
jak nazwiesz tą metodę. Jeśli przejdziesz null, istnieje ryzyko wystąpienia WYJĄTKÓW w czasie wykonywania.
anonimowa klasa na ratunek.
teraz możesz utworzyć anonimową klasę, która implementuje ten interfejs i przekazać ją metodzie zapewniającej implementację jej metod zgodnie z Twoimi potrzebami.
przykład poniżej.

// Interface from external Libraryinterface External { public void interfaceMethod();}class CalledClass { // Method to called. Takes an argument of interface type public void toBeCalled(External e) { e.interfaceMethod(); }}

powyższy kod ma interfejs z pojedynczą metodą i klasą, której metodę trzeba wywołać z kodu.

metoda tej klasy pobiera argument typu interface, ale nie masz klasy, która implementuje ten interfejs.
jeśli przekażesz null do argumentu metody, od razu wyrzuci java.lang.NullPointerException.
zobacz jak możesz wywołać tę metodę używając klasy Anonymous.

class CallingClass { // Main method public static void main(String args) { CalledClass obj = new CalledClass(); // call method using Anonymous class obj.toBeCalled(new External() { public void interfaceMethod() { // your code } }); }}

zwróć uwagę na użycie anonimowej implementacji interfejsu do wywołania metody.
to największa zaleta anonimowych klas.
4. Statyczna Klasa zagnieżdżona
statyczna Klasa zdefiniowana wewnątrz innej klasy jest statyczną klasą zagnieżdżoną. Jest ona zdefiniowana tak jak zwykła Klasa poprzedzona statycznym słowem kluczowym.
pamiętaj, że nie ma nic takiego jak Klasa statyczna, statyczna zagnieżdżona klasa jest tylko statycznym członkiem jej zewnętrznej klasy.
ponieważ jest elementem statycznym, następujące zastosowanie ma do statycznej klasy zagnieżdżonej.

  1. może być dostępny przez klasę zewnętrzną bezpośrednio bez jej wystąpienia.
  2. może uzyskać dostęp tylko do statycznych elementów swojej zewnętrznej klasy, ale nie do zmiennych instancji ani metod.

przykład statycznej klasy zagnieżdżonej

public class Outer { // static nested class static class Inner { public void innerMethod() { System.out.println("Method of static nested class"); } } public void outerMethod() { System.out.println("Method of outer class"); } public static void main(String args) { // access inner class directly Inner inner = new Inner(); // call nested class method inner.innerMethod(); }}

Jak widać z powyższego przykładu, aby uzyskać dostęp do statycznej klasy zagnieżdżonej, instancja klasy zewnętrznej nie jest wymagana i można do niej uzyskać bezpośredni dostęp.
zauważ, że obiekt statycznej klasy zagnieżdżonej nie może uzyskać dostępu do niestatycznych elementów klasy zewnętrznej. W powyższym przykładzie zagnieżdżona instancja klasy nie może wywołać outerMethod klasy zewnętrznej.

dostosujmy

  1. gdy Klasa zawierająca klasę wewnętrzną jest kompilowana, to generowane są 2 pliki klas :
    jeden dla klasy zewnętrznej i jeden dla klasy wewnętrznej.
    Przyklad, Zewnetrzny.class I Outer$Inner.klasa dla klasy zewnętrznej Klasa zewnętrzna i wewnętrzna Klasa wewnętrzna odpowiednio..
  2. plik klasy wewnętrznej nie może być bezpośrednio wykonany za pomocą polecenia java.
  3. normalna Klasa wewnętrzna nie może mieć static elementów danych lub metod.
  4. Klasa wewnętrzna może mieć konstruktor.
  5. Klasa lokalna metody może być utworzona tylko wewnątrz metody, w której jest zdefiniowana.
  6. metoda Klasa lokalna zdefiniowana w metodzie static może mieć dostęp tylko do static członków klasy zamykającej.
  7. anonimowa klasa, która implementuje interfejs, może zaimplementować tylko jeden interfejs w przeciwieństwie do zwykłych klas, które mogą zaimplementować wiele.
  8. Klasa anonimowa nie może rozszerzyć klasy i zaimplementować interfejsu w tym samym czasie, co normalne klasy.
  9. anonimowe definicje klas kończą się znakiem }; (zwróć uwagę na średnik).
  10. klasy anonimowe, które są zdefiniowane jako argument podczas wywołania metody kończą się znakiem}); (zwróć uwagę na średnik).
  11. nie można wywołać metody na anonimowym odwołaniu do klasy, która nie jest obecna w rzeczywistej klasie.
  12. Klasa wewnętrzna poprzedzona static jest znana jako klasa zagnieżdżona, a nie klasa wewnętrzna.

Leave a Reply