Inner class in java
Inner class meaning
As its name states, a class inside another class is called an Inner Class.
sisemmillä luokilla on erityinen suhde sen sisältävään luokkaan sikäli, että sillä on pääsy kaikkiin ulomman luokan jäseniin(jopa private
ykkösiin).
tämä johtuu siitä, että sisempi luokka on myös ulomman luokan jäsen kuten muutkin kentät ja menetelmät.
koska sisempi luokka on toisen luokan sisällä oleva luokka, voidaan sitä kutsua myös sisäkkäiseksi luokaksi.
tyypit sisempi Luokka
sisempi luokka voi olla seuraavia tyyppejä
- normaali tai säännöllinen tai sisäkkäinen sisempi Luokka (yleensä kutsutaan vain sisemmäksi luokaksi)
- menetelmä paikallinen sisempi Luokka.
- nimetön sisäinen luokka.
- Staattinen sisäkkäinen Luokka
1. Sisäkkäinen sisempi Luokka
tässä jaksossa kaivetaan esiin kaikki sisemmän luokan yksityiskohdat. Yksinkertaisuuden vuoksi tarkastellaan seuraavia luokkia
class Outer { private String outerField = "Outer"; class Inner { private String innerField = "Inner"; }}
tässä ulompi on ulompi luokka ja sisempi on sisempi luokka, joka sisältyy ulomman sisälle.
sisemmän luokan objekti
sisempi luokka on toisen luokan sisällä. Sisältävää luokkaa kutsutaan ulkoluokaksi. Näin ollen sisempi luokka ei voi olla olemassa ilman ulompaa luokkaa ja sama pätee sen objektiin(tai instanssiin).
sisemmän luokan objektia ei voi olla olemassa ilman ulomman luokan objektia.
tämä tarkoittaa sitä, että sisemmän luokan instanssin luomiseen tarvitaan ulomman luokan instanssi.
näin ollen sisemmän luokan objekti voidaan luoda alla annetulla menetelmällä.
// first, create object of outer classOuter outerObject = new Outer();// create object of inner classInner innerObject = outerObject.new Inner();
kuten esimerkistä käy selvästi ilmi, sisemmän luokan objektin luomiseksi tarvitaan ulomman luokan objekti.
on olemassa myös lyhytkätinen menetelmä sisemmän luokan objektin luomiseksi.
Inner innerObject = new Outer().new Inner();
tämä menetelmä vaatii myös ulomman luokan objektin.
vain Remember….An sisemmän luokan objektia ei voida luoda ilman sen sisältävää objektia (tai ulompaa luokkaa).
sisäisen luokan objektin luominen ulomman luokan sisällä
edellinen esimerkki olettaa, että olet instantioimassa sisäistä luokkaa jostain ulomman luokan ulkopuolelta.
, mutta useimmissa tapauksissa sisemmän luokan objekti vaaditaan vain ulomman luokan sisälle, koska ulompi luokka käyttää sisempää luokkaa.
Miten siis luodaan sisemmän luokan objekti ulomman luokan sisältä?
tarkastellaan jäljempänä muutettua näyteluokkaa.
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"; }}
huomaa rivi Inner innerObject = new Inner();
.
aiemmin todettiin, että sisemmän luokan objektia ei voi luoda ilman ulomman luokan objektia, mutta yllä oleva koodinpätkä tekee sen. Hämmentynyt !!!!
yllä oleva syntaksi on pätevä, koska se kirjoitetaan ulomman luokan menetelmän sisällä.
kun tätä koodia suoritetaan, on jo olemassa ulkoluokan esiintymä, joka suorittaa menetelmää.
muista aina, että luodakseen (tai päästäkseen) sisemmän luokan objektin, tulisi olla ulomman luokan instanssi.
Yhteenveto,
- kun sisemmän luokan objekti luodaan ulomman luokan sisältä, se voidaan luoda suoraan muodossa
Inner innerObject = new Inner();
. - kun sisemmän luokan objekti luodaan ulomman luokan ulkopuolelta, se on luotava nimellä
Inner innerObject = new Outer().new Inner();
.
kun tulostetaan ulko – ja sisäluokan esineitä, Seuraavassa on tuloste:
Outer class instance: Outer@659e0bfd
Inner class instance : Ulompi$Inner@2a139a55
viittaa ulomman luokan instanssiin, kenttiin ja menetelmiin sisemmästä luokasta
sisempi luokka kuuluu myös sen sisältävään luokkaan kuten muutkin kentät ja menetelmät.
siten se voi käyttää muita ulomman luokan kenttiä ja menetelmiä samalla tavalla kuin muut kentät ja menetelmät pääsevät suoraan toistensa kimppuun.
tämä pätee, kun haetaan ulomman luokan kenttiä ja menetelmiä sisemmästä luokasta.
, mutta viitattaessa ulkoluokan instanssiin on olemassa ero. Luokan nykyilmaisuun viitataan hakusanalla this
.
jos on kyse sisemmästä luokasta, käyttämällä this
sisemmästä luokasta tarkoitetaan nykyistä sisemmän luokan ilmentymää eikä sen ulompaa luokkaa.
jotta voidaan viitata esimerkiksi ulompaan luokkaan sisemmästä luokasta, on lisättävä luokan nimi this
hakusanaan.
käytä siis Outer.this
syntaksia viitataksesi ulomman luokan instanssiin sisemmästä luokasta.
katso alla oleva esimerkki ymmärtämiseksi.
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); } }}
Output
Outer field: Outer
Inner instance:
Outer instance :
2. Menetelmä paikallinen Sisäluokka
kuten nimestä voi päätellä, menetelmän sisällä määritelty luokka on menetelmä paikallinen Sisäluokka.
kyllä, se on mahdollista.
voit määritellä luokan menetelmän sisällä alla esitetyllä tavalla.
// 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}
yllä olevalla koodilla on ulompi luokka, joka sisältää menetelmän.
tässä menetelmässä määritellään luokka, joka on menetelmärungon sisällä, joten sitä kutsutaan menetelmän paikalliseksi sisäluokaksi.
huomaa, että sisemmällä luokalla on myös oma metodimäärityksensä.
menetelmän ilmentäminen paikallinen sisempi Luokka
edeltävä koodi ilmoittaa menetelmän paikallinen sisempi luokka, mutta se ei luo mitään sisemmän luokan objektia.
nyt herää kysymys, miten menetelmän paikallisen sisäluokan objekti luodaan.
koska menetelmän sisällä on määritelty paikallinen sisäluokka, se näkyy vain kyseisen menetelmän sisällä ja sen kohde voidaan myös luoda vain kyseisen menetelmän sisällä.
alla oleva koodi luo menetelmän objektin paikallisen sisäluokan ja kutsuu sen menetelmää.
// 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(); }}
kun Yllä oleva koodi suoritetaan, seuraavassa on tuloste
menetelmä paikallinen sisäluokkamenetelmä, jota kutsutaan
tämä osoittaa, että kun ulomman luokan menetelmää kutsutaan, se luo sisemmän luokan objektin ja kutsuu sisemmän luokan menetelmää.
menetelmä paikallinen sisempi Luokka : muistettavat pisteet
lausuma, joka luo menetelmän objektin, tulee kirjoittaa luokan kehon ulkopuolelle.
näin ollen linjan Inner innerObject = new Inner();
pitäisi tulla paikallisluokan päätyttyä.
- menetelmän paikallinen sisäinen luokka voidaan instantioida vain sen menetelmän sisällä, jossa se on ilmoitettu.
tämä on järkevää, koska metodiluokka on näkyvissä vain menetelmän sisällä, joten sen kohde voidaan luoda vain kyseisen menetelmän sisällä. - menetelmä paikallinen sisempi luokka ei voi käyttää sen menetelmän paikallisia muuttujia, jossa se on ilmoitettu.
jos sen on päästävä niihin käsiksi, ne on merkittäväfinal
.
tämä pätee ennen java 8: aa. - et voi käyttää menetelmän paikallista muuttujaa menetelmän paikallisen sisemmän luokan sisällä ja määrittää sitä sitten uudelleen. Tämä on kääntäjän virhe.
tämä pätee java 8: sta, koska java 8: aa edeltävät versiot eivät salli edes sisemmän luokan sisällä olevan method local-muuttujan käyttöä. - menetelmä paikallinen sisempi luokka voi käyttää sen luokan kenttiä ja muita menetelmiä, johon sisemmän luokan sisältävä menetelmä kuuluu.
- menetelmä paikallinen sisempi luokka voi käyttää
static
kenttiä ja muitastatic
sen luokan menetelmiä, johon sisemmän luokan sisältävä menetelmä kuuluu vain, jos sisältävä menetelmä onstatic
.
3. Nimetön sisempi Luokka
nimetön tarkoittaa, jonka nimi ei ole tiedossa. Javan yhteydessä nimetön luokka on sellainen, jolla ei ole nimeä.
nimetön luokka koskee vain sisempiä luokkia, koska ulommilla luokilla tulee olla nimi.
nimetön luokka on sisempi luokka, koska se määritellään aina toisen luokan sisällä.
tyypit nimetön Luokka Javassa
todellisuudessa nimetön luokka on jo olemassa olevan luokan tai rajapinnan toteutus, joka kirjoitetaan jossain muualla, mutta määritellään uudelleen toisen luokan sisällä tarpeen mukaan.
tämä saattaa kuulostaa hämmentävältä, mutta seuraavat esimerkit selventävät käsitystä.
sen perusteella, onko nimetön Luokka jonkin luokan toteutus vai rajapinta, se voi kuulua seuraaviin kahteen luokkaan
A. Luokan alaluokka
aloitetaan esimerkistä ensin
// 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"); } };}
yllä olevassa esimerkissä on jo luotu luokkanimetty Verkkosivusto.
toinen Luokkahakukoneisto määrittelee tämän luokan uudelleen, toteuttaa menetelmänsä ja määrittää sen vertailumuuttujaksi, joka on samaa tyyppiä kuin varsinainen Luokka.
uutta menetelmää voidaan käyttää myös tämän viitemuuttujan avulla.
muista, että juuri toteutettu nimetön luokka on varsinaisen luokan alaluokka.
se seuraa polymorfismia ja sen objekti voidaan siirtää minne tahansa, mihin Website-luokan objekti on odotettavissa.
käy alla oleva esimerkki läpi kuvitukseksi.
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); }}
sen sijaan, että Website-luokan toteutusta määriteltäisiin etukäteen, se voidaan määritellä tarvittaessa, eli kutsumalla getwebsite-menetelmää.
näin ollen päämenetelmää voidaan muuttaa, koska
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"); } });}
edellä mainittua toteutusta ei ole osoitettu millekään viitemuuttujalle, sillä ei ole nimeä ja näin ollen nimetön.
B. rajapinnan toteuttaja
nimetön luokka voidaan määritellä myös rajapinnan toteuttajaksi.
tässä tapauksessa se määrittelee rajapinnassa ilmoitettujen menetelmien toteutuksen ja voidaan siirtää missä tahansa rajapinnan kohde on odotettavissa.
katso alla oleva esimerkki asian selvittämiseksi.
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); }}
kuten ennenkin, rajapinnan toteuttaminen anonyyminä luokkana voidaan tarvittaessa luoda kuten alla on esitetty.
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"); } });}
new
hakusanan käyttö ennen käyttöliittymän nimeä. Anonyymi luokka on ainoa paikka, jossa se on mahdollista. polymorfismi nimettömissä luokissa
kuten aiemmin todettiin, anonyymit luokat seuraavat polymorfismia.
koska ne ovat alaluokkia, niiden tulisi noudattaa polymorfismia. Tässä osiossa kerrotaan yksityiskohtaisesti, miten.
tarkastellaan alla olevaa luokkaa.
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(); }}
yllä oleva koodi määrittelee luokan metallin yhdellä menetelmällä.
tämä luokka toteutetaan jälleen anonyymisti toisen luokan Metaldriverissä, jossa sen määritelmään lisätään uusi menetelmä, joka ei esiinny varsinaisessa luokassa.
nyt kun tätä uutta menetelmää kutsutaan, kääntäjä valittaa virheellä
menetelmä hasLustre() on tyypille Metalli määrittelemätön.
tämä johtuu siitä, että nimetön luokka on alaluokka, kun taas viite on todellista luokkaa(joka on vanhempi).
kääntäjä ei löytänyt uutta menetelmää vanhempainluokasta ja merkitsi virheen.
näin virhe vahvistaa Kaksi faktaa:
(i) nimetön luokka on varsinaisen luokan alaluokka, ja
(ii) nimetön luokkamäärittely seuraa polymorfismia.
anonyymin luokan
käyttö oletetaan, että on kutsuttava menetelmä, joka ottaa jonkin tyypin argumentin, joka on liittymä.
nyt tämä rajapinta kuuluu johonkin ulkoiseen kirjastoon, eikä sinulla ole luokkaa, joka toteuttaa tämän rajapinnan.
miten tätä menetelmää kutsutaan. Jos ohitat null
, juoksuaikapoikkeusten riski on olemassa.
nimetön Luokka hätiin.
nyt voit luoda nimettömän luokan, joka toteuttaa tämän rajapinnan ja siirtää sen menetelmän kautta, joka tarjoaa sen menetelmien toteuttamisen tarpeidesi mukaan.
seuraa esimerkki.
// 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(); }}
yllä olevassa koodissa on rajapinta, jossa on yksi menetelmä ja luokka, jonka metodiin sinun täytyy soittaa koodistasi.
tämän luokan menetelmä vaatii tyypin käyttöliittymän argumentin, mutta sinulla ei ole luokkaa, joka toteuttaa tämän rajapinnan.
jos menee null
metodiargumenttiin, se heittää heti java.lang.NullPointerException
.
Katso, miten tätä menetelmää voi kutsua anonyymiksi luokaksi.
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 } }); }}
huomaa, että menetelmää kutsutaan anonyymin rajapintatoteutuksen avulla.
tämä on anonyymien luokkien suurin hyöty.
4. Staattinen sisäkkäinen Luokka
toisen luokan sisällä määritelty staattinen luokka on staattinen sisäkkäinen Luokka. Se määritellään aivan kuten normaali luokka, jota edeltää staattinen avainsana.
muista, ettei ole mitään yhtä staattista luokkaa, staattinen sisäkkäinen luokka on vain sen ulomman luokan staattinen jäsen.
koska se on staattinen jäsen, sovelletaan seuraavaa staattiseen sisäkkäiseen luokkaan.
- siihen pääsee ulompi Luokka suoraan ilman sen esiintymää.
- se pääsee käsiksi vain ulkoluokkansa staattisiin jäseniin, mutta ei instanssimuuttujiinsa tai menetelmiinsä.
Staattinen sisäkkäinen luokkaesimerkki
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(); }}
kuten yllä olevasta esimerkistä näkyy, että staattisen sisäkkäisen luokan käyttöön ei tarvita ulkoluokan ilmentymää, vaan siihen pääsee suoraan.
huomaa, että staattisen sisäkkäisen luokan objekti ei pääse käsiksi ulkoluokan ei-staattisiin jäseniin. Yllä olevassa esimerkissä sisäkkäinen Luokka-ilmentymä ei voi vedota outerMethod
ulompaan luokkaan.
niputetaan
- kun sisemmän luokan sisältävä Luokka kootaan, syntyy 2 luokkatiedostoa :
yksi ulomman luokan ja yksi sisemmän luokan osalta.
Esimerkki, Ulompi.luokka ja ulompi$sisempi.luokka on ulompi Luokka ulompi ja sisempi Luokka sisempi.. - sisemmän luokan Luokkatiedostoa ei voi suorittaa suoraan java-komennolla.
- normaalilla sisäisellä luokalla ei voi olla
static
datajäseniä tai menetelmiä. - sisemmällä luokalla voi olla rakentaja.
- menetelmän paikallisluokka voidaan instantioida vain sen menetelmän sisällä, jossa se on määritelty.
- menetelmässä
static
määritelty paikallinen luokka voi käyttää vainstatic
sulkuluokan jäseniä. - anonyymi luokka, joka toteuttaa rajapinnan, voi toteuttaa vain yhden rajapinnan erotuksena normaaleista luokista, jotka voivat toteuttaa monia.
- nimetön luokka ei voi laajentaa luokkaa ja toteuttaa rajapintaa samaan aikaan kuin normaalit luokat.
- anonyymit luokkamääritelmät päättyvät}; (huomaa puolipisteessä).
- anonyymit luokat, jotka määritellään argumentiksi, kun menetelmää kutsutaan päätteellä}); (huomaa puolipiste).
- anonyymiin luokkaviittaukseen ei voi kutsua menetelmää, jota ei esiinny varsinaisessa luokassa.
- sisempi luokka, jota edeltää
static
, tunnetaan sisäkkäisenä luokkana, ei sisempänä luokkana.
Leave a Reply