Vgnezdeni razredi so razredi, ki so prijavljeni kot člani drugih razredov ali obsegov. Uganjanje razredov je eden od načinov za boljšo organizacijo kode. Recimo na primer, da imate ugnezden razred (znan tudi kot vrhunski razred), ki shranjuje predmete v spremenljivo matriko, čemur sledi razred iteratorja, ki vrne vsak predmet. Namesto da bi onesnažili imenski prostor razreda najvišje ravni, bi lahko razred iteratorja razglasil kot člana razreda zbirke matrike, ki jo je mogoče spremeniti. To deluje, ker sta oba tesno povezana.
V Javi so ugnezdeni razredi kategorizirani kot bodisi statični razredi članov ali notranji razredi. Notranji razredi so nestatični razredi članov, lokalni razredi ali anonimni razredi. V tej vadnici boste izvedeli, kako delati s statičnimi razredi članov in tremi vrstami notranjih razredov v kodi Java.
Izogibajte se puščanju pomnilnika v ugnezdenih razredih
Oglejte si tudi namig Java, povezan s to vadnico, kjer boste izvedeli, zakaj so ugnezdeni razredi ranljivi za uhajanje pomnilnika.
Statični razredi v Javi
V mojem Java 101 vaje Razredi in predmeti v Javi ste se naučili, kako statična polja in statične metode prijaviti kot člane razreda. V inicializaciji razredov in predmetov v Javi ste se naučili, kako statične inicializatorje prijaviti kot člane razreda. Zdaj se boste naučili, kako prijaviti statični razredi. Formalno znan kot statični razredi članov, to so ugnezdeni razredi, ki jih prijavite na isti ravni kot te druge statične entitete z uporabo statično
ključna beseda. Tu je primer statične izjave razreda člana:
razred C {static int f; statična praznina m () {} statična {f = 2; } statični razred D {// člani}}
Ta primer uvaja razred najvišje ravni C
s statičnim poljem f
, statična metoda m ()
, statični inicializator in statični razred D
. Opazite to D
je član C
. Statično polje f
, statična metoda m ()
, in statični inicializator sta tudi člana C
. Ker vsi ti elementi pripadajo razredu C
, je znan kot ogradni razred. Razred D
je znan kot zaprti razred.
Pravila za ograjevanje in dostop
Čeprav je zaprt, statični članski razred ne more dostopati do polj primerka razreda in priklicati njegove metode primerka. Lahko pa dostopa do statičnih polj zaprtega razreda in prikliče njegove statične metode, tudi tiste člane, ki so deklarirani zasebno
. Za prikaz, seznam 1 razglasi EnclosingClass
z ugnezdenim SMClass
.
Seznam 1. Izjava o statičnem razredu člana (EnclosingClass.java, različica 1)
razred EnclosingClass {zasebni statični niz s; zasebna statična praznina m1 () {System.out.println (s); } statična praznina m2 () {SMClass.accessEnclosingClass (); } statični razred SMClass {static void accessEnclosingClass () {s = "Poklican iz metode SMClass accessEnclosingClass ()"; m1 (); } void accessEnclosingClass2 () {m2 (); }}}
V seznamu 1 je naveden razred najvišje ravni z imenom EnclosingClass
s predavalnim poljem s
, razredne metode m1 ()
in m2 ()
in razred statičnega člana SMClass
. SMClass
razglasi metodo razreda accessEnclosingClass ()
in primerka accessEnclosingClass2 ()
. Upoštevajte naslednje:
m2 ()
je priklicSMClass
jeaccessEnclosingClass ()
metoda zahtevaSMClass.
predpono, keraccessEnclosingClass ()
je razglašenastatično
.accessEnclosingClass ()
lahko dostopaEnclosingClass
jes
polje in pokličite njegovom1 ()
metoda, čeprav sta bili obe razglašenizasebno
.
Seznam 2 predstavlja izvorno kodo SMCDemo
aplikacijski razred, ki prikazuje, kako sklicati SMClass
je accessEnclosingClass ()
metoda. Prav tako prikazuje, kako narediti primerek SMClass
in prikličete njegovo accessEnclosingClass2 ()
metoda primerka.
Seznam 2. Klicanje metod statičnega člana (SMCDemo.java)
javni razred SMCDemo {public static void main (String [] args) {EnclosingClass.SMClass.accessEnclosingClass (); EnclosingClass.SMClass smc = novo EnclosingClass.SMClass (); smc.accessEnclosingClass2 (); }}
Kot je prikazano v seznamu 2, če želite priklicati metodo najvišjega razreda iz zaprtega razreda, morate pred imenom predpisanega razreda dodati ime njegovega zaprtega razreda. Če želite primeriti zaprti razred, morate pred imenom predpisa dodati ime njegovega zaprtega razreda. Nato lahko prikličete metodo primerka na običajen način.
Sestavi seznam 1 in 2, kot sledi:
javac * .java
Ko prevedete zaprti razred, ki vsebuje razred statičnega člana, prevajalnik ustvari datoteko razreda za razred statičnega člana, katerega ime je sestavljeno iz imena njegovega razreda, znaka za dolar in imena razreda statičnega člana. V tem primeru je sestavljanje rezultatov v EnclosingClass $ SMCClass.class
in EnclosingClass.class
.
Zaženite aplikacijo na naslednji način:
java SMCDemo
Upoštevati morate naslednje rezultate:
Klicano iz metode SMClass's accessEnclosingClass () Klicano iz metode SMClass's accessEnclosingClass ()
Primer: Statični razredi in Java 2D
Java knjižnica standardnih razredov je izvajalna knjižnica datotek razredov, ki shranjujejo prevedene razrede in druge referenčne vrste. Knjižnica vključuje številne primere statičnih učnih razredov, nekatere pa najdemo v razredih 2D geometrijskih oblik Java, ki se nahajajo v java.awt.geom
paket. (O paketih boste izvedeli v naslednjem Java 101 vadnico.)
The Ellipse2D
razred najden v java.awt.geom
opisuje elipso, ki je definirana z okvirjalnim pravokotnikom v smislu (x, y) zgornjega levega kota skupaj s širino in višino. Naslednji fragment kode kaže, da temelji arhitektura tega razreda Float
in Dvojno
statični članski razredi, ki sta podrazred Ellipse2D
:
javni abstraktni razred Ellipse2D razširja RectangularShape {javni statični razred Float razširja Ellipse2D izvaja Serializable {javni float x, y, širina, višina; public Float () {} public Float (float x, float y, float w, float h) {setFrame (x, y, w, h); } javni dvojni getX () {return (dvojni) x; } // metode dodatnih primerov} javni statični razred Double extends Ellipse2D implementira Serializable {public double x, y, width, height; public Double () {} public Double (dvojni x, dvojni y, dvojni w, dvojni h) {setFrame (x, y, w, h); } javni dvojni getX () {return x; } // dodatne metode primerka} javna logična vrednost vsebuje (dvojni x, dvojni y) {// ...} // dodatne metode primerka, ki jih delijo podrazredi Float, Double in drugi // Ellipse2D}
The Float
in Dvojno
razredi podaljšajo Ellipse2D
, ki zagotavlja plavajočo vejico in plavajočo vejico z dvojno natančnostjo Ellipse2D
izvedb. Razvijalci uporabljajo Float
za zmanjšanje porabe pomnilnika, zlasti ker boste morda potrebovali na tisoče ali več teh predmetov za izdelavo ene same 2D scene. Uporabljamo Dvojno
kadar je potrebna večja natančnost.
Izvlečka ne morete ustvariti s primerkom Ellipse2D
razreda, lahko pa ustvarite primere Float
ali Dvojno
. Lahko tudi podaljšate Ellipse2D
za opis oblike po meri, ki temelji na elipsi.
Kot primer recimo, da želite predstaviti a Krog2D
razred, ki ni prisoten v java.awt.geom
paket. Naslednji fragment kode prikazuje, kako bi ustvarili datoteko Ellipse2D
objekt z izvedbo s plavajočo vejico:
Ellipse2D e2d = novo Ellipse2D.Float (10.0f, 10.0f, 20.0f, 30.0f);
Naslednji fragment kode prikazuje, kako bi ustvarili datoteko Ellipse2D
objekt z dvojno natančnostjo izvedbe s plavajočo vejico:
Ellipse2D e2d = nova Ellipse2D.Dvojna (10,0, 10,0, 20,0, 30,0);
Zdaj lahko prikličete katero koli metodo, navedeno v Float
ali Dvojno
s klicanjem metode na vrnjenem Ellipse2D
sklic (npr. e2d.getX ()
). Na enak način se lahko sklicujete na katero koli skupno metodo Float
in Dvojno
, in ki so prijavljeni v Ellipse2D
. Primer je:
e2d. vsebuje (2.0, 3.0)
S tem je uvod v statične razrede članov zaključen. Nato si bomo ogledali notranje razrede, ki so nestatični razredi članov, lokalni razredi ali anonimni razredi. Naučili se boste delati z vsemi tremi vrstami notranjega razreda.
prenos Prenesite kodo Prenesite izvorno kodo za primere v tej vadnici. Ustvaril Jeff Friesen za JavaWorld.Notranji razredi, tip 1: Nestatični razredi članov
Že prej ste se naučili v Java 101 serija, kako razglasiti nestatična (primer) polja, metode in konstruktorje kot člane razreda. Lahko tudi prijavite nestatični razredi članov, ki so ugnezdeni nestatični razredi, ki jih prijavite na isti ravni kot polja primerka, metode in konstruktorji. Razmislite o tem primeru:
razred C {int f; praznina m () {} C () {f = 2; } razred D {// člani}}
Tu predstavljamo razred najvišje stopnje C
s primerom polja f
, metoda primerka m ()
, konstruktor in nestatični članski razred D
. Vse te entitete so člani razreda C
, ki jih obdaja. Vendar pa so te entitete, za razliko od prejšnjega primera, povezane z primeriC
in ne z C
razred sam.
Vsak primerek nestatičnega razreda člana je implicitno povezan z primerkom njegovega zaprtega razreda. Metode primerkov nestatičnega člana lahko pokličejo metode primerka zaprtega razreda in dostopajo do njegovih polj primerka. Za prikaz tega dostopa seznam 3 razglasi EnclosingClass
z ugnezdenim NSMClass
.
Seznam 3. Razglasite zaprti razred z ugnezdenim ne-statičnim članskim razredom (EnclosingClass.java, različica 2)
razred EnclosingClass {private String s; zasebna praznina m () {System.out.println (s); } razred NSMClass {void accessEnclosingClass () {s = "Poklican iz metode accessEnclosingClass () NSMClass"; m (); }}}
V seznamu 3 je razglašen najvišji razred z imenom EnclosingClass
s primerom polja s
, metoda primerka m ()
in nestatični razred NSMClass
. Poleg tega NSMClass
razglasi metodo primerka accessEnclosingClass ()
.
Ker accessEnclosingClass ()
je nestatičen, NSMClass
mora biti instanciran, preden je to metodo mogoče poklicati. Ta primerek mora biti izveden prek primerka EnclosingClass
, kot je prikazano na seznamu 4.
Seznam 4. NSMCDemo.java
javni razred NSMCDemo {public static void main (String [] args) {EnclosingClass ec = new EnclosingClass (); ec.new NSMClass (). accessEnclosingClass (); }}
Seznam 4 glavni ()
metoda najprej ustvari primerek EnclosingClass
in sklic shrani v lokalno spremenljivko ek
. The glavni ()
metoda nato uporabi EnclosingClass
sklic kot predpono novo
operater, da ustvari primerek NSMClass
. The NSMClass
referenca se nato uporabi za klic accessEnclosingClass ()
.
Ali naj uporabim 'new' s sklicevanjem na razred ograde?
Predpona novo
s sklicevanjem na zaprti razred je redek. Namesto tega običajno pokličete konstruktor zaprtega razreda znotraj konstruktorja ali metode primerka njegovega zaprtega razreda.
Sestavi seznam 3 in 4, kot sledi:
javac * .java
Ko prevedete ogradni razred, ki vsebuje ne-statični razred, prevajalnik ustvari datoteko razreda za ne-statični razred, katerega ime je sestavljeno iz imena njegovega razreda, znaka za dolar in ne-statičnega razreda. ime. V tem primeru je sestavljanje rezultatov v EnclosingClass $ NSMCClass.class
in EnclosingClass.class
.
Zaženite aplikacijo na naslednji način:
java NSMCDemo
Upoštevati morate naslednje rezultate:
Klicano iz metode accessEnclosingClass () NSMClass
Kdaj (in kako) izpolniti pogoje za "to"
Koda zaprtega razreda lahko s kvalificirano rezervirano besedo pridobi referenco na svoj primerek zaprtega razreda to
z imenom priloženega razreda in operaterjem dostopa do člana (.
). Na primer, če je koda znotraj accessEnclosingClass ()
potreben za sklic na njegovo EnclosingClass
primer, bi določil EnclosingClass.this
. Ker prevajalnik za to nalogo ustvari kodo, je določanje te predpone redko.
Primer: Nestatični razredi članov v HashMap-u
Standardna knjižnica razredov vključuje tudi nestatične razrede članov in razrede statičnih članov. Za ta primer si bomo ogledali HashMap
razred, ki je del ogrodja zbirk Java v java.util
paket. HashMap
, ki opisuje izvedbo zemljevida na osnovi razprševalne tabele, vključuje več nestatičnih razredov članov.
Na primer KeySet
nestatični članski razred opisuje niz, ki temelji pogled tipk na zemljevidu. Naslednji fragment kode se nanaša na priloženi KeySet
razred do svojega HashMap
ogradni razred:
javni razred HashMap razširja AbstractMap izvaja Map, Cloneable, Serializable {// različni člani končni razred KeySet razširja AbstractSet {// različni člani} // različni člani}
The in
sintakse so primeri generiki, zbirka sorodnih jezikovnih funkcij, ki pomagajo prevajalniku uveljaviti varnost tipa. V prihodnosti bom predstavil generike Java 101 vadnica. Zaenkrat morate le vedeti, da te sintakse pomagajo prevajalniku uveljaviti vrsto ključnih predmetov, ki jih je mogoče shraniti na zemljevidu in v nabor ključev, ter vrsto predmetov vrednosti, ki jih je mogoče shraniti na zemljevidu.
HashMap
zagotavlja a keySet ()
metoda, ki ustvari primerek KeySet
po potrebi vrne ta primerek ali predpomnjeni primerek. Tu je celotna metoda: