vnitřní třídy v Javě
vnitřní třída znamená
jak uvádí její název, třída uvnitř jiné třídy se nazývá vnitřní Třída.
vnitřní třídy sdílejí zvláštní vztah s jeho obsahující třídou v tom, že má přístup ke všem členům vnější třídy (I private
).
je to proto, že vnitřní třída je také členem vnější třídy stejně jako ostatní pole a metody.
protože vnitřní třída je třída uvnitř jiné třídy, může být také označována jako vnořená třída.
typy vnitřních tříd
vnitřní třída může být následujících typů.
- normální nebo pravidelná nebo vnořená vnitřní třída (obvykle označovaná jako jen vnitřní třída)
- metoda místní vnitřní třída.
- anonymní vnitřní třída.
- statická vnořená třída
1. Vnořená vnitřní Třída
tato část bude kopat do všech detailů vnitřní třídy. Pro jednoduchost zvažte následující třídy
class Outer { private String outerField = "Outer"; class Inner { private String innerField = "Inner"; }}
zde vnější je vnější třída A vnitřní je vnitřní třída, která je obsažena uvnitř vnější.
vytvoření objektu vnitřní třídy
vnitřní třída je uvnitř jiné třídy. Obsahující třída se nazývá vnější třída. Vnitřní třída tedy nemůže existovat bez vnější třídy A totéž platí pro její objekt (nebo instanci).
objekt vnitřní třídy nemůže existovat bez objektu vnější třídy.
to znamená, že pro vytvoření instance vnitřní třídy musíte mít instanci vnější třídy.
objekt vnitřní třídy lze tedy vytvořit níže uvedenou metodou.
// first, create object of outer classOuter outerObject = new Outer();// create object of inner classInner innerObject = outerObject.new Inner();
jak je zřejmé z příkladu, pro vytvoření objektu vnitřní třídy je nutný objekt vnější třídy.
existuje také metoda krátké ruky pro vytvoření objektu vnitřní třídy.
Inner innerObject = new Outer().new Inner();
tato metoda také vyžaduje objekt vnější třídy.
jen Remember….An objekt vnitřní třídy nemůže být vytvořen bez objektu jeho obsahujícího (nebo vnější třídy).
vytvoření objektu vnitřní třídy v rámci vnější třídy
předchozí příklad předpokládá, že vytváříte vnitřní třídu odněkud mimo vnější třídu.
ale ve většině případů je objekt vnitřní třídy vyžadován pouze uvnitř vnější třídy, protože vnější třída používá vnitřní třídu.
jak tedy vytvoříme objekt vnitřní třídy zevnitř vnější třídy?
zvažte níže upravenou třídu vzorků.
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"; }}
Všimněte si řádku Inner innerObject = new Inner();
.
dříve bylo uvedeno, že objekt vnitřní třídy nelze vytvořit bez objektu vnější třídy, ale výše uvedený fragment kódu to dělá. Zmatený !!!!
výše uvedená syntaxe je platná, protože je zapsána uvnitř metody vnější třídy.
při spuštění tohoto kódu již existuje instance vnější třídy, která tuto metodu spouští.
vždy pamatujte, že pro vytvoření (nebo přístup) objektu vnitřní třídy by měla existovat instance vnější třídy.
shrnout,
- když je objekt vnitřní třídy vytvořen z vnější třídy, může být vytvořen přímo jako
Inner innerObject = new Inner();
. - když je objekt vnitřní třídy vytvořen z vnější třídy, musí být vytvořen jako
Inner innerObject = new Outer().new Inner();
.
při tisku objektů vnější a vnitřní třídy je generován výstup:
instance vnější třídy: vnější@659e0bfd
instance vnitřní třídy : Vnější$Inner@2a139a55
odkazující na instanci vnější třídy, pole a metody z vnitřní třídy
vnitřní třída je také členem její obsahující třídy jako ostatní pole a metody.
může tedy přistupovat k jiným polím a metodám vnější třídy stejným způsobem jako ostatní pole a metody k sobě přistupují přímo.
to platí při přístupu k vnějším polím třídy a metodám z vnitřní třídy.
ale při odkazování na instanci vnější třídy je rozdíl. Pro odkaz na aktuální instanci třídy se používá klíčové slovo this
.
v případě vnitřní třídy se použití this
uvnitř vnitřní třídy týká aktuální instance vnitřní třídy a ne její vnější třídy.
pro odkazování na instanci vnější třídy z vnitřní třídy musíme do klíčového slova this
přidat název třídy.
Chcete-li tedy odkazovat na instanci vnější třídy z vnitřní třídy, použijte syntaxi Outer.this
.
viz níže příklad pro pochopení.
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); } }}
výstup
vnější pole: vnější
vnitřní instance:
vnější instance :
2. Metoda Local Inner Class
jak název napovídá, třída definovaná uvnitř metody je metoda Local Inner Class.
Ano, Je to možné.
můžete definovat třídu uvnitř metody, jak je uvedeno níže.
// 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}
výše uvedený kód má třídu vnější obsahující metodu.
tato metoda definuje třídu, která je uvnitř těla metody, proto se nazývá metoda místní vnitřní třída.
Všimněte si, že vnitřní třída má také svou vlastní definici metody.
instance metody lokální vnitřní třída
předcházející kód deklaruje metodu lokální vnitřní třída, ale nevytváří žádný objekt vnitřní třídy.
nyní vyvstává otázka, jak vytvořit objekt metody místní vnitřní třídy.
protože je uvnitř metody definována lokální vnitřní třída metody, je viditelná pouze uvnitř této metody a její objekt může být také vytvořen pouze uvnitř této metody.
níže kód vytvoří objekt metody místní vnitřní třídy a volá její metodu.
// 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(); }}
po provedení výše uvedeného kódu následuje výstup
metoda místní metoda vnitřní třídy s názvem
To ukazuje, že při volání metody vnější třídy vytvoří objekt vnitřní třídy a zavolá metodu vnitřní třídy.
metoda místní vnitřní Třída: body k zapamatování
příkaz, který vytvoří objekt metody místní vnitřní třída, by měl být zapsán mimo tělo třídy.
řádek Inner innerObject = new Inner();
by tedy měl přijít po ukončení místní třídy.
- metodu lokální vnitřní třídy lze vytvořit pouze uvnitř metody, ve které je deklarována.
to dává smysl, protože třída metody je viditelná pouze uvnitř metody, takže její objekt může být vytvořen pouze uvnitř této metody. - metoda místní vnitřní třída nemá přístup k lokálním proměnným metody, ve které je deklarována.
pokud k nim potřebuje přístup, měly by být označenyfinal
.
to platí před Javou 8. - nemůžete přistupovat k místní proměnné metody uvnitř místní vnitřní třídy metody a poté ji znovu přiřadit. Bude to chyba kompilátoru.
to platí pro Javu 8, protože verze před Javou 8 vám ani neumožní přístup k místní proměnné metody uvnitř vnitřní třídy. - metoda místní vnitřní třída může přistupovat k polím a dalším metodám třídy, do které metoda obsahující vnitřní třídu patří.
- metoda místní vnitřní třída může přistupovat k polím
static
a dalším metodámstatic
třídy, do které metoda obsahující vnitřní třídu patří, pouze pokud je metoda obsahujícístatic
.
3. Anonymní vnitřní třídy
anonymní znamená, jehož jméno není známo. V kontextu Javy je anonymní třída ta, která nemá žádné jméno.
termín anonymní třída je použitelný pouze pro vnitřní třídy, protože vnější třídy by měly mít název.
anonymní třída je vnitřní třída, protože bude vždy definována uvnitř jiné třídy.
typy anonymní třídy v Javě
ve skutečnosti je anonymní třída implementací již existující třídy nebo rozhraní, které je napsáno někde jinde, ale je definováno znovu uvnitř jiné třídy podle potřeby.
může to znít matoucí, ale následující příklady objasní koncept.
na základě toho, zda je anonymní třída implementací třídy nebo rozhraní, může patřit do následujících dvou kategorií
a. Podtřída třídy
začněme příkladem první
// 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"); } };}
ve výše uvedeném příkladu existuje třída s názvem Website, která je již vytvořena.
další třída SearchEngine předefinuje tuto třídu, implementuje její metodu a přiřadí ji referenční proměnné, která je stejného typu jako skutečná třída.
nově implementovanou metodu je také možné volat pomocí této referenční proměnné.
nezapomeňte, že nově implementovaná Třída Anonymous je podtřídou skutečné třídy.
následuje polymorfismus a jeho objekt může být předán kdekoli se očekává objekt třídy webových stránek.
Projděte si níže uvedený příklad pro ilustraci.
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); }}
místo předdefinování implementace třídy Website ji lze definovat tam, kde je to nutné, tedy při volání metody getWebsite.
tedy hlavní metodu lze modifikovat 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"); } });}
výše uvedená implementace není přiřazena žádné referenční proměnné, nemá název a tudíž název Anonymous.
B. implementátor rozhraní
anonymní třída může být také definována jako implementátor rozhraní.
v tomto případě bude definovat implementaci metod deklarovaných v rozhraní a může být předána kdekoli se očekává objekt rozhraní.
viz níže uvedený příklad, aby bylo jasné.
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); }}
stejně jako dříve lze implementaci rozhraní jako anonymní třídy vytvořit tam, kde je to požadováno, jak je uvedeno níže.
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
před názvem rozhraní. Anonymní třída je jediné místo, kde je to možné.polymorfismus v anonymních třídách
jak bylo uvedeno výše, anonymní třídy následují polymorfismus.
protože se jedná o podtřídy, měly by následovat polymorfismus. Tato část podrobně popisuje, jak.
zvažte níže uvedenou třídu.
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(); }}
výše uvedený kód definuje třídu kovu jedinou metodou.
tato třída je opět implementována anonymně v jiné třídě MetalDriver, kde je do její definice přidána nová metoda, která není přítomna ve skutečné třídě.
Nyní, když je tato nová metoda volána, kompilátor si stěžuje na chybu
metoda hasLustre () není pro typ Metal definována.
je to proto, že anonymní třída je podtřída, zatímco reference je skutečná třída(což je rodič).
kompilátor nemohl najít novou metodu v nadřazené třídě a označí chybu.
chyba tedy stanoví dvě skutečnosti:
(i) anonymní třída je podtřída skutečné třídy a
(ii) anonymní definice třídy následuje polymorfismus.
použití anonymní třídy
Předpokládejme, že potřebujete zavolat metodu, která má argument typu, který je rozhraním.
nyní toto rozhraní patří do nějaké externí knihovny a nemáte třídu, která implementuje toto rozhraní.
jak budete volat tuto metodu. Pokud projdete null
, existuje riziko výjimek z doby běhu.
anonymní třída na záchranu.
nyní můžete vytvořit anonymní třídu, která implementuje toto rozhraní a předá ji přes metodu poskytující implementaci jeho metod podle vašich potřeb.
následuje příklad.
// 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(); }}
výše uvedený kód má rozhraní s jedinou metodou a třídou, jejíž metodu musíte volat z kódu.
metoda této třídy má argument typu rozhraní, ale nemáte třídu, která implementuje toto rozhraní.
pokud předáte null
argumentu metody, okamžitě hodí java.lang.NullPointerException
.
podívejte se, jak můžete volat tuto metodu pomocí anonymní třídy.
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 } }); }}
Všimněte si použití anonymní implementace rozhraní pro volání metody.
to je největší výhoda anonymních tříd.
4. Statická vnořená třída
statická třída, která je definována uvnitř jiné třídy, je statická vnořená třída. Je definován stejně jako normální třída předchází statické Klíčové slovo.
nezapomeňte, že neexistuje nic jako statická třída, statická vnořená třída je pouze statickým členem její vnější třídy.
vzhledem k tomu, že se jedná o statický člen, platí následující pro statickou vnořenou třídu.
- je přístupný vnější třídou přímo, aniž by měl její instanci.
- může přistupovat pouze ke statickým členům své vnější třídy, ale ne k proměnným nebo metodám instance.
příklad statické vnořené třídy
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 můžete vidět z výše uvedeného příkladu, že pro přístup ke statické vnořené třídě není vyžadována instance vnější třídy a lze k ní přistupovat přímo.
Všimněte si, že objekt statické vnořené třídy nemá přístup k nestatickým členům vnější třídy. Ve výše uvedeném příkladu vnořená instance třídy nemůže vyvolat outerMethod
vnější třídy.
pojďme vyladit v
- když je zkompilována třída obsahující vnitřní třídu, vygenerují se 2 soubory třídy:
jeden pro vnější třídu a jeden pro vnitřní třídu.
Příklad, Vnější.třída A vnější$vnitřní.třída pro vnější třídu vnější a vnitřní třídu vnitřní.. - soubor třídy vnitřní třídy nelze přímo spustit pomocí příkazu java.
- normální vnitřní třída nemůže mít
static
datové členy nebo metody. - vnitřní třída může mít Konstruktor.
- lokální třídu metody lze vytvořit pouze uvnitř metody, ve které je definována.
- místní třída metody definovaná v metodě
static
má přístup pouze kstatic
členům uzavřené třídy. - anonymní třída, která implementuje rozhraní, může implementovat pouze jedno rozhraní na rozdíl od běžných tříd, které mohou implementovat mnoho.
- anonymní třída nemůže rozšířit třídu a implementovat rozhraní současně, které normální třídy mohou.
- anonymní definice třídy končí na}; (Všimněte si dvojtečky).
- anonymní třídy, které jsou definovány jako argument při volání metody končící na }); (Všimněte si polodrážky).
- nemůžete volat metodu na anonymní odkaz třídy, který není přítomen ve skutečné třídě.
- vnitřní třída předcházející
static
je známá jako vnořená třída, nikoli vnitřní třída.
Leave a Reply