inre klasser i java

inre klass som betyder
som namnet säger kallas en klass i en annan klass en inre klass.
inre klasser delar speciell relation med sin innehållande klass genom att den har tillgång till alla medlemmar i den yttre klassen(även private).
detta beror på att en inre klass också är medlem i yttre klass precis som andra fält och metoder.
eftersom en inre klass är en klass i en annan klass kan den också kallas en kapslad klass.
typer av inre klasser
en inre klass kan vara av följande typer.

  1. Normal eller vanlig eller kapslad inre klass(normalt kallad bara inre klass)
  2. metod lokal inre klass.
  3. anonym inre klass.
  4. statisk kapslad klass

1. Kapslad inre klass
detta avsnitt kommer att gräva i alla detaljer i en inre klass. För enkelhetens skull, överväga följande klasser

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

här yttre är den yttre klassen och inre är den inre klassen som finns inuti yttre.

skapa objekt av inre klass
en inre klass är inne i en annan klass. Innehåller klass kallas yttre klass. Således kan en inre klass inte existera utan yttre klass och detsamma gäller dess objekt(eller instans).
ett objekt av inre klass kan inte existera utan ett objekt av yttre klass.
det betyder att för att skapa en instans av inre klass måste du ha en instans av yttre klass.
således kan objekt av inre klass skapas med den nedan angivna metoden.

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

som framgår av exemplet, för att skapa ett objekt av inre klass, är ett objekt av yttre klass nödvändigt.
det finns också en korthandsmetod för att skapa inre klassobjekt.

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

denna metod kräver också yttre klassobjekt.
bara Remember….An objekt av inre klass kan inte skapas utan ett objekt av dess innehållande (eller yttre klass).

skapa inre klassobjekt inom yttre klass
föregående exempel förutsätter att du instanser inre klass från någonstans utanför den yttre klassen.
men i de flesta fall krävs ett objekt av inre klass endast inom den yttre klassen, eftersom yttre klassen använder sig av inre klass.
så hur skapar vi ett objekt av inre klass inifrån yttre klass?
överväg modifierad provklass nedan.

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"; }}

Lägg märke till raden Inner innerObject = new Inner();.
tidigare angavs att ett inre klassobjekt inte kan skapas utan ett objekt av yttre klass men ovanstående kodavsnitt gör det. Förvirrad !!!!
ovanstående syntax är giltig eftersom den är skriven i en metod för yttre klass.
när den här koden körs finns det redan en instans av yttre klass närvarande, som kör metoden.

kom alltid ihåg, för att skapa(eller komma åt) ett objekt av inre klass, bör det finnas en instans av yttre klass.

för att sammanfatta,

  1. när ett objekt av inre klass skapas inifrån yttre klass kan det skapas direkt som Inner innerObject = new Inner();.
  2. när ett objekt av inre klass skapas från utsidan av yttre klass måste det skapas som Inner innerObject = new Outer().new Inner();.

När objekt av yttre och inre klass skrivs ut, följer utmatningen:

yttre klass instans: yttre@659e0bfd
inre klass instans : Yttre $ Inner@2a139a55

refererar till yttre Klassinstans, fält och metoder från inre klass
en inre klass är också medlem i sin innehållande klass som andra fält och metoder.
Således kan den komma åt andra fält och metoder i ytterklassen på samma sätt som andra fält och metoder kommer åt varandra direkt.
detta gäller vid åtkomst till yttre klassfält och metoder från inre klass.

Men när man hänvisar till förekomsten av yttre klass är det en skillnad. För att referera till den aktuella instansen av en klass används this nyckelord.
vid inre klass, med this inuti inre klass hänvisar till nuvarande instans av inre klass och inte dess yttre klass.
för att referera till instans av yttre klass från inre klass måste vi lägga till klassnamn till this nyckelord.

för att referera till yttre klassinstans från inre klass, använd Outer.this syntax.
se nedan exempel för att förstå.

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); } }}

utgång

yttre fält: yttre
inre instans:
yttre instans :

2. Metod lokal inre klass
som namnet antyder är en klass definierad i en metod en metod lokal inre klass.
Ja, det är möjligt.
du kan definiera en klass i en metod som visas nedan.

// 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}

ovanstående kod har en klass yttre innehåller en metod.
denna metod definierar en klass som är inne i metodkroppen, därav kallad metod lokal inre klass.
Lägg märke till att Inner class också har sin egen metoddefinition.

Instantiating en metod lokal inre klass
föregående kod förklarar en metod lokal inre klass men det skapar inte något objekt av inre klass.
nu uppstår frågan, hur man skapar ett objekt av metod lokal inre klass.
eftersom en metod lokal inre klass definieras inuti en metod är den synlig endast inuti den metoden och dess objekt kan också skapas endast inuti den metoden.
nedan kod skapar ett objekt av metod lokal inre klass och kallar sin 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(); }}

När ovanstående kod körs följer utmatningen

metod lokal inre klassmetod som kallas

detta visar att när yttre klassmetod kallas skapar den ett objekt av inre klass och kallar inner class-metoden.

metod lokal inre klass : poäng att komma ihåg
uttalande som skapar ett objekt av metod lokal inre klass ska skrivas utanför klasskroppen.
således bör linjen Inner innerObject = new Inner(); komma efter att den lokala klassen slutar.

  1. en metod lokal inre klass kan instansieras endast inom den metod där den deklareras.
    detta är vettigt eftersom en metodklass endast är synlig i metoden, så dess objekt kan skapas endast i den metoden.
  2. en metod lokal inre klass kan inte komma åt de lokala variablerna i metoden där den deklareras.
    om den behöver komma åt dem ska de markeras final.
    detta gäller före java 8.
  3. du kan inte komma åt en lokal metodvariabel i en lokal metodklass och sedan tilldela den igen. Detta kommer att vara ett kompilatorfel.
    detta gäller från java 8 eftersom versioner före java 8 inte ens tillåter dig att komma åt en metod lokal variabel inuti den inre klassen.
  4. en metod lokal inre klass kan komma åt fälten och andra metoder i den klass som metoden som innehåller inre klass tillhör.
  5. en metod lokal inre klass kan komma åt fälten static och andra static metoder för den klass som metoden som innehåller inre klass tillhör endast när den innehållande metoden är static.

3. Anonyma inre klasser
anonyma betyder vars namn inte är känt. I samband med java är en anonym klass en som inte har något namn.
termen anonym klass är endast tillämplig på inre klasser eftersom yttre klasser ska ha ett namn.
en anonym klass är en inre klass eftersom den alltid kommer att definieras i en annan klass.

Typer Av Anonym klass i java
i själva verket är en anonym klass en implementering av en redan befintlig klass eller ett gränssnitt som skrivs någon annanstans men det definieras igen i en annan klass efter behov.
detta kan låta förvirrande men de exempel som följer kommer att klargöra konceptet.

baserat på om den anonyma klassen är en implementering av en klass eller ett gränssnitt kan den tillhöra följande två kategorier

A. Underklass av en klass
Låt oss börja med ett exempel först

// 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"); } };}

i exemplet ovan finns det en klass som heter webbplats som redan är skapad.
en annan klass SearchEngine omdefinierar denna klass, implementerar sin metod och tilldelar den till en referensvariabel som är av samma typ som den faktiska klassen.
det är också möjligt att ringa den nyligen implementerade metoden med hjälp av denna referensvariabel.

kom ihåg att den nyligen implementerade anonyma klassen är en underklass av den faktiska klassen.
det följer polymorfism och dess objekt kan skickas var som helst objektet för Webbplatsklass förväntas.
gå igenom exemplet nedan för illustration.

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); }}

istället för att fördefiniera implementeringen av Webbplatsklassen kan den definieras där det behövs, det vill säga när du anropar getWebsite-metoden.
således kan huvudmetoden modifieras som

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"); } });}

ovanstående implementering är inte tilldelad någon referensvariabel, den har inget namn och därmed namnet anonym.

det är inte nödvändigt att båda klasserna finns i samma fil eller paket. De kan placeras var som helst i förhållande till varandra.

B. Implementer av gränssnitt
en anonym klass kan också definieras som implementer av ett gränssnitt.
i det här fallet kommer det att definiera implementeringen av metoder som deklareras i gränssnittet och kan skickas var som helst som gränssnittsobjektet förväntas.
se nedan exempel för att göra det klart.

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); }}

som tidigare kan implementering av gränssnitt som anonym klass skapas där det krävs enligt nedan.

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"); } });}
Lägg märke till användningen av new nyckelord före gränssnittsnamnet. Anonym klass är den enda platsen där det är möjligt.

polymorfism i anonyma klasser
som tidigare nämnts följer anonyma klasser polymorfism.
eftersom de är underklasser bör de följa polymorfism. Det här avsnittet kommer att beskriva hur.
Tänk på nedanstående klass.

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(); }}

ovanstående kod definierar en Klassmetall med en enda metod.
denna klass implementeras igen anonymt i en annan klass MetalDriver där en ny metod läggs till dess definition som inte finns i den faktiska klassen.

nu när den här nya metoden kallas klagar kompilatorn med ett fel

metoden hasLustre() är odefinierad för typen metall.

detta beror på att anonym klass är en underklass medan referensen är av faktisk klass(som är förälder).
kompilatorn kunde inte hitta den nya metoden i överordnad klass och flaggar ett fel.

således fastställer felet två fakta:
(i) anonym klass är en underklass av faktisk klass, och
(ii) anonyma klassdefinitioner följer polymorfism.

användning av anonym klass
Antag att du måste ringa en metod som tar ett argument av en typ som är ett gränssnitt.
nu hör detta gränssnitt till något externt bibliotek och du har inte en klass som implementerar detta gränssnitt.
hur kommer du att kalla den här metoden. Om du passerar null finns det risk för undantag för körtid.
anonym klass till undsättning.
nu kan du skapa en anonym klass som implementerar detta gränssnitt och skicka det över metoden som ger implementering av dess metoder enligt dina behov.
exempel följer.

// 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(); }}

ovanstående kod har ett gränssnitt med en enda metod och en klass vars metod du behöver ringa från din kod.

metod för denna klass tar ett argument av typgränssnitt men du har inte en klass som implementerar detta gränssnitt.
om du skickar nulltill metodargumentet kommer det genast att kasta en java.lang.NullPointerException.
ta en titt på hur du kan ringa den här metoden med anonym klass.

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 } }); }}

Lägg märke till användningen av Anonym gränssnittsimplementering för att ringa metoden.
Detta är den största fördelen med anonyma klasser.
4. Statisk kapslad klass
en statisk klass som definieras i en annan klass är en statisk kapslad klass. Det definieras precis som en vanlig klass föregås med statiska sökord.
kom ihåg att det inte finns något som statisk klass, en statisk kapslad klass är bara en statisk medlem i sin yttre klass.
eftersom det är en statisk medlem, gäller följande för en statisk kapslad klass.

  1. den kan nås av den yttre klassen direkt utan att ha sin instans.
  2. det kan bara komma åt statiska medlemmar i sin yttre klass men inte dess instansvariabler eller metoder.

exempel på Statisk kapslad klass

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(); }}

som du kan se från ovanstående exempel, att för att komma åt statisk kapslad klass krävs inte en instans av yttre klass och den kan nås direkt.
Observera att objekt av statisk kapslad klass inte kan komma åt icke-statiska medlemmar av yttre klass. I exemplet ovan kan kapslade klass instans inte åberopa outerMethod av yttre klass.

Låt oss tweak in

  1. när en klass som innehåller inre klass sammanställs genereras 2 klassfiler :
    en för yttre klass och en för inre klass.
    Exempel, Yttre.klass och yttre$inre.klass för yttre klass yttre och inre klass inre respektive..
  2. klassfil av inner class kan inte köras direkt med java-kommandot.
  3. en normal inre klass kan inte ha static datamedlemmar eller metoder.
  4. en inre klass kan ha en konstruktör.
  5. en metod lokal klass kan instansieras endast inom den metod där den definieras.
  6. en metod lokal klass definierad i static metod kan bara komma åt static medlemmar i den omslutande klassen.
  7. en anonym klass som implementerar ett gränssnitt, kan implementera endast ett gränssnitt i motsats till normala klasser som kan implementera många.
  8. en anonym klass kan inte förlänga en klass och implementera ett gränssnitt samtidigt som normala klasser kan.
  9. anonyma klassdefinitioner slutar med}; (Lägg märke till semikolon).
  10. anonyma klasser som definieras som ett argument medan man anropar en metod slutar med }); (Lägg märke till semikolon).
  11. du kan inte ringa en metod på anonym klassreferens som inte finns i själva klassen.
  12. en inre klass föregås med static är känd som en kapslad klass, inte en inre klass.

Leave a Reply