Programovanie

Statické triedy a vnútorné triedy v Jave

Vnorené triedy sú triedy, ktoré sú deklarované ako členovia iných tried alebo rozsahov. Vnorenie tried je jedným zo spôsobov, ako lepšie usporiadať svoj kód. Povedzme napríklad, že máte vnorenú triedu (známa tiež ako a trieda najvyššej úrovne), ktorý ukladá objekty do zmeniteľného poľa, za ktorým nasleduje trieda iterátora, ktorá vracia každý objekt. Namiesto znečisťovania spoločného priestoru triedy najvyššej úrovne môžete triedu iterátora vyhlásiť za člena triedy kolekcie s možnosťou zmeny veľkosti. Funguje to preto, lebo tieto dva spolu úzko súvisia.

V Jave sú vnorené triedy kategorizované ako buď statické členské triedy alebo vnútorné triedy. Vnútorné triedy sú nestatické členské triedy, miestne triedy alebo anonymné triedy. V tomto výučbe sa dozviete, ako pracovať so statickými členskými triedami a tromi typmi vnútorných tried v kóde Java.

Zabráňte úniku pamäte vo vnorených triedach

Prečítajte si tiež tip pre jazyk Java spojený s týmto tutoriálom, kde sa dozviete, prečo sú vnorené triedy náchylné na úniky pamäte.

Statické triedy v prostredí Java

V mojom Java 101 tutoriál Triedy a objekty v prostredí Java, ste sa naučili deklarovať statické polia a statické metódy ako členov triedy. V časti Inicializácia tried a objektov v prostredí Java ste sa naučili, ako deklarovať statické inicializátory ako členov triedy. Teraz sa naučíte, ako deklarovať statické triedy. Formálne známy ako statické členské triedy, sú to vnorené triedy, ktoré deklarujete na rovnakej úrovni ako tieto ostatné statické entity pomocou statický kľúčové slovo. Tu je príklad statickej deklarácie triedy člena:

 trieda C {static int f; static void m () {} static {f = 2; } statická trieda D {// members}} 

Tento príklad predstavuje triedu najvyššej úrovne C. so statickým poľom f, statická metóda m (), statický inicializátor a trieda statického člena D. Všimni si D je členom C.. Statické pole f, statická metóda m ()a statický inicializátor sú tiež členmi C.. Pretože všetky tieto prvky patria do triedy C., je známy ako uzatváracia trieda. Trieda D je známy ako uzavretá trieda.

Pravidlá ochrany a prístupu

Aj keď je statická členská trieda uzavretá, nemôže získať prístup k poliam inštancie obklopujúcej triedy a vyvolať jej inštančné metódy. Môže však získať prístup k statickým poliam uzatvárajúcej triedy a vyvolať jej statické metódy, dokonca aj tých členov, ktorí sú deklarovaní súkromné. Na preukázanie zoznam 1 deklaruje EnclosingClass s vnoreným SMClass.

Zoznam 1. Deklarovanie triedy statického člena (EnclosingClass.java, verzia 1)

 class EnclosingClass {private static String s; private static void m1 () {System.out.println (s); } static void m2 () {SMClass.accessEnclosingClass (); } statická trieda SMClass {static void accessEnclosingClass () {s = "Volané z metódy accessEnclosingClass () SMClass"; ml (); } void accessEnclosingClass2 () {m2 (); }}} 

Výpis 1 deklaruje triedu najvyššej úrovne s názvom EnclosingClass s poľom triedy s, triedne metódy m1 () a m2 ()a trieda statického člena SMClass. SMClass deklaruje triednu metódu accessEnclosingClass () a inštančná metóda accessEnclosingClass2 (). Nezabudnite na toto:

  • m2 ()Vyvolanie SMClassje accessEnclosingClass () metóda vyžaduje SMClass. prefix pretože accessEnclosingClass () je vyhlásený statický.
  • accessEnclosingClass () má prístup EnclosingClassje s pole a zavolajte jeho m1 () napriek tomu, že obidve boli vyhlásené súkromné.

Výpis 2 predstavuje zdrojový kód súboru SMCDemo aplikačná trieda, ktorá demonštruje, ako sa má vyvolať SMClassje accessEnclosingClass () metóda. Ukazuje tiež, ako vytvoriť inštanciu SMClass a vyvolať jeho accessEnclosingClass2 () inštančná metóda.

Zoznam 2. Vyvolanie metód statickej členskej triedy (SMCDemo.java)

 public class SMCDemo {public static void main (String [] args) {EnclosingClass.SMClass.accessEnclosingClass (); EnclosingClass.SMClass smc = nový EnclosingClass.SMClass (); smc.accessEnclosingClass2 (); }} 

Ako je uvedené v zozname 2, ak chcete vyvolať metódu triedy najvyššej úrovne z uzavretej triedy, musíte pred názov uzavretej triedy vložiť názov jej priloženej triedy. Rovnako tak, aby ste vytvorili inštanciu uzavretej triedy, musíte pred názov tejto triedy pridať predponu. Potom môžete metódu inštancie vyvolať bežným spôsobom.

Zostavte zoznamy 1 a 2 takto:

 javac * .java 

Keď kompilujete priloženú triedu, ktorá obsahuje statickú členskú triedu, kompilátor vytvorí súbor triedy pre statickú členskú triedu, ktorej názov pozostáva z názvu jej priloženej triedy, znaku znaku dolára a názvu statickej členskej triedy. V takom prípade bude výsledkom kompilácie EnclosingClass $ SMCClass.class a EnclosingClass.class.

Spustite aplikáciu nasledovne:

 java SMCDemo 

Mali by ste dodržiavať nasledujúci výstup:

 Volané z metódy SMClass's accessEnclosingClass () Volané z metódy SMClass's accessEnclosingClass () 

Príklad: Statické triedy a Java 2D

Java štandardná triedna knižnica je runtime knižnica súborov triedy, ktorá uchováva skompilované triedy a ďalšie referenčné typy. Knižnica obsahuje početné príklady tried statických členov, z ktorých niektoré sa nachádzajú v triedach Java 2D geometrických tvarov umiestnených v java.awt.geom balíček. (O balíčkoch sa dozviete v ďalšom Java 101 návod.)

The Ellipse2D trieda nájdená v java.awt.geom popisuje elipsu, ktorá je definovaná rámcovým obdĺžnikom v zmysle (x, y) ľavého horného rohu spolu s rozsahmi šírky a výšky. Nasledujúci fragment kódu ukazuje, že architektúra tejto triedy je založená na Plavák a Dvojitý statické členské triedy, ktoré obidve podtriedy Ellipse2D:

 public abstract class Ellipse2D extends RectangularShape {public static class Float extends Ellipse2D implements Serializable {public float x, y, width, height; public Float () {} public Float (float x, float y, float w, float h) {setFrame (x, y, w, h); } public double getX () {return (double) x; } // ďalšie inštančné metódy} public static class Double extends Ellipse2D implements Serializable {public double x, y, width, height; public Double () {} public Double (double x, double y, double w, double h) {setFrame (x, y, w, h); } public double getX () {return x; } // ďalšie metódy inštancie} public boolean obsahuje (double x, double y) {// ...} // ďalšie metódy inštancie zdieľané Float, Double a ďalšími // podtriedami Ellipse2D} 

The Plavák a Dvojitý triedy predlžujú Ellipse2D, ktorý poskytuje pohyblivú desatinnú čiarku a dvojitú presnosť s pohyblivou desatinnou čiarkou Ellipse2D implementácie. Vývojári používajú Plavák na zníženie spotreby pamäte, najmä preto, že na skonštruovanie jednej 2D scény budete možno potrebovať tisíce alebo viac týchto objektov. Používame Dvojitý keď sa vyžaduje vyššia presnosť.

Abstrakt nemôžete vytvoriť okamžite Ellipse2D triedy, ale môžete vytvoriť inštanciu buď Plavák alebo Dvojitý. Môžete tiež predĺžiť Ellipse2D na popísanie vlastného tvaru, ktorý je založený na elipsy.

Ako príklad povedzme, že chcete predstaviť a Circle2D triedy, ktorá nie je prítomná v java.awt.geom balíček. Nasledujúci fragment kódu ukazuje, ako by ste vytvorili súbor Ellipse2D objekt s plávajúcou desatinnou čiarkou:

 Ellipse2D e2d = nový Ellipse2D.Float (10.0f, 10.0f, 20.0f, 30.0f); 

Nasledujúci fragment kódu ukazuje, ako by ste vytvorili súbor Ellipse2D objekt s implementáciou s pohyblivou rádovou čiarkou s dvojitou presnosťou:

 Ellipse2D e2d = nový Ellipse2D.Double (10.0, 10.0, 20.0, 30.0); 

Teraz môžete vyvolať ktorúkoľvek z metód deklarovaných v Plavák alebo Dvojitý vyvolaním metódy na vrátenom Ellipse2D odkaz (napr. e2d.getX ()). Rovnakým spôsobom môžete vyvolať ktorúkoľvek z bežných metód Plavák a Dvojitý, a ktoré sú deklarované v Ellipse2D. Príkladom je:

 e2d. obsahuje (2,0; 3,0) 

Týmto je dokončený úvod do statických tried členov. Ďalej sa pozrieme na vnútorné triedy, čo sú nestatické členské triedy, miestne triedy alebo anonymné triedy. Naučíte sa, ako pracovať so všetkými tromi typmi vnútorných tried.

stiahnuť Získajte kód Stiahnite si zdrojový kód pre príklady v tejto príručke. Vytvoril Jeff Friesen pre JavaWorld.

Vnútorné triedy, typ 1: Nestatické členské triedy

Už predtým ste sa naučili v Java 101 série, ako deklarovať nestatické polia (inštancie), metódy a konštruktory ako členov triedy. Môžete tiež vyhlásiť nestatické triedy členov, čo sú vnorené nestatické triedy, ktoré deklarujete na rovnakej úrovni ako polia inštancie, metódy a konštruktory. Zvážte tento príklad:

 trieda C {int f; void m () {} C () {f = 2; } trieda D {// členovia}} 

Tu predstavujeme triedu najvyššej úrovne C. s inštančným poľom finštančná metóda m (), konštruktor a nestatická trieda členov D. Všetky tieto subjekty sú členmi triedy C., ktorý ich uzatvára. Avšak na rozdiel od predchádzajúceho príkladu sú tieto inštančné entity spojené s prípadyC. a nie s C. samotná trieda.

Každá inštancia nestatickej členskej triedy je implicitne spojená s inštanciou jej obklopujúcej triedy. Metódy inštancie nestatickej členskej triedy môžu volať metódy inštancie uzatvárajúcej triedy a pristupovať k jej poliam inštancií. Na preukázanie tohto prístupu zoznam 3 deklaruje EnclosingClass s vnoreným NSMClass.

Zoznam 3. Deklarujte uzatvárajúcu triedu so vnorenou nestatickou členskou triedou (EnclosingClass.java, verzia 2).

 trieda EnclosingClass {private String s; private void m () {System.out.println (s); } trieda NSMClass {void accessEnclosingClass () {s = "Volané z metódy NSEVEleanEnclosingClass ()"; m (); }}} 

Výpis 3 deklaruje triedu najvyššej úrovne s názvom EnclosingClass s inštančným poľom sinštančná metóda m ()a nestatická trieda členov NSMClass. Ďalej NSMClass deklaruje inštančnú metódu accessEnclosingClass ().

Pretože accessEnclosingClass () je nestatický, NSMClass pred volaním tejto metódy je potrebné vytvoriť inštanciu. Táto inštancia sa musí uskutočniť prostredníctvom inštancie EnclosingClass, ako je uvedené v zozname 4.

Zoznam 4. NSMCDemo.java

 public class NSMCDemo {public static void main (String [] args) {EnclosingClass ec = new EnclosingClass (); ec.new NSMClass (). accessEnclosingClass (); }} 

Zoznam 4 hlavný() metóda najskôr inštancuje EnclosingClass a uloží jeho referenciu do lokálnej premennej ec. The hlavný() metóda potom používa EnclosingClass odkaz ako predpona k Nový operátor, s cieľom vytvoriť inštanciu NSMClass. The NSMClass odkaz sa potom použije na volanie accessEnclosingClass ().

Mám použiť výraz „nový“ s odkazom na priloženú triedu?

Predpona Nový s odkazom na priloženú triedu je zriedkavé. Namiesto toho zvyčajne zavoláte konštruktor uzavretej triedy z konštruktora alebo z inštančnej metódy jej uzavretej triedy.

Zostavte zoznamy 3 a 4 takto:

 javac * .java 

Keď kompilujete uzatvárajúcu triedu, ktorá obsahuje nestatickú členskú triedu, kompilátor vytvorí súbor triedy pre nestatickú členskú triedu, ktorej názov pozostáva z názvu jej uzatvárajúcej triedy, znaku znaku dolára a nestatickej členskej triedy názov. V takom prípade bude výsledkom kompilácie EnclosingClass $ NSMCClass.class a EnclosingClass.class.

Spustite aplikáciu nasledovne:

 java NSMCDemo 

Mali by ste dodržiavať nasledujúci výstup:

 Volá sa metódou NSMClass accessEnclosingClass () 

Kedy (a ako) kvalifikovať „toto“

Kód uzavretej triedy môže získať odkaz na svoju inštanciu uzavretej triedy kvalifikovaním vyhradeného slova toto s menom priloženej triedy a operátorom prístupu členov (.). Napríklad ak kód v rámci accessEnclosingClass () potrebné na získanie odkazu na jeho EnclosingClass inštanciu, určilo by to EnclosingClass.this. Pretože kompilátor generuje kód na splnenie tejto úlohy, zadanie tejto predpony je zriedkavé.

Príklad: Nestatické členské triedy v HashMap

Knižnica štandardných tried obsahuje nestatické triedy členov aj triedy statických členov. V tomto príklade sa pozrieme na HashMap triedy, ktorá je súčasťou rámca Java Collections Framework v java.util balíček. HashMap, ktorý popisuje implementáciu mapy pomocou hash tabuľky, obsahuje niekoľko nestatických tried členov.

Napríklad KeySet nestatická členská trieda popisuje množinu vyhliadka kľúčov obsiahnutých na mape. Nasledujúci fragment kódu sa týka priloženého KeySet triedy do svojej HashMap priložená trieda:

 verejná trieda HashMap rozširuje AbstractMap implementuje Map, Cloneable, Serializable {// rôzni členovia finálna trieda KeySet rozširuje AbstractSet {// rôzni členovia} // rôzni členovia} 

The a syntaxe sú príkladmi generiká, sada funkcií súvisiaceho jazyka, ktoré pomáhajú kompilátoru presadiť bezpečnosť typu. V najbližšej dobe predstavím generiká Java 101 návod. Zatiaľ potrebujete iba vedieť, že tieto syntaxe pomáhajú kompilátoru presadiť typ kľúčových objektov, ktoré je možné uložiť na mape a v súprave kľúčov, a typ hodnotných objektov, ktoré je možné uložiť na mape.

HashMap poskytuje a keySet () metóda, ktorá vytvára inštancie KeySet ak je to potrebné, a vráti túto inštanciu alebo inštanciu uloženú v pamäti. Tu je úplná metóda:

$config[zx-auto] not found$config[zx-overlay] not found