Programavimas

Statinės klasės ir vidinės klasės „Java“

Lizdinės klasės yra klasės, kurios yra deklaruojamos kaip kitų klasių ar taikymo srities nariai. Klasių lizdai yra vienas iš būdų, kaip geriau tvarkyti kodą. Pvz., Tarkime, kad turite ne lizdų klasę (dar vadinamą a aukščiausio lygio klasė), kuriame objektai saugomi keičiamo dydžio masyve, po to seka iteratoriaus klasė, kuri grąžina kiekvieną objektą. Užuot teršę aukščiausio lygio klasės vardų sritį, galite paskelbti iteratorių klasę kaip keičiamų masyvų kolekcijos klasės narį. Tai veikia, nes abu yra glaudžiai susiję.

„Java“ sistemoje įdėtos klasės skirstomos į abi kategorijas statinių narių klasės arba vidinės klasės. Vidinės klasės yra nestatinės narių klasės, vietinės klasės arba anoniminės klasės. Šioje pamokoje sužinosite, kaip dirbti su statinėmis narių klasėmis ir trimis vidinių klasių tipais jūsų „Java“ kode.

Venkite atminties nutekėjimo įdėtose klasėse

Taip pat žiūrėkite „Java“ patarimą, susietą su šia mokymo programa, kur sužinosite, kodėl įdėtos klasės yra pažeidžiamos atminties nutekėjimo.

Statinės klasės „Java“

Mano „Java 101“ pamoka „Java“ klasės ir objektai, jūs išmokote deklaruoti statinius laukus ir statinius metodus kaip klasės narius. „Java“ klasės ir objektų inicijavime sužinojote, kaip statinius inicialus paskelbti klasės nariais. Dabar sužinosite, kaip deklaruoti statinės klasės. Oficialiai žinomas kaip statinių narių klasės, tai yra įdėtos klasės, kurias deklaruojate tame pačiame lygyje kaip ir kiti statiniai objektai, naudodami statinis raktinis žodis. Čia pateikiamas statinės narių klasės deklaracijos pavyzdys:

 C klasė {static int f; static void m () {} statinis {f = 2; } statinė D klasė {// nariai}} 

Šis pavyzdys pristato aukščiausio lygio klasę C su statiniu lauku f, statinis metodas m (), statinis inicializatorius ir statinio nario klasė D. Pastebėti, kad D yra C. Statinis laukas f, statinis metodas m ()ir statinis inicializatorius taip pat yra C. Kadangi visi šie elementai priklauso klasei C, jis yra žinomas kaip uždari klasė. Klasė D yra žinomas kaip uždara klasė.

Uždarymo ir prieigos taisyklės

Nors statinė nario klasė yra uždara, ji negali pasiekti uždarančios klasės egzempliorių laukų ir pasinaudoti jos egzempliorių metodais. Tačiau jis gali prieiti prie uždarančios klasės statinių laukų ir pasinaudoti savo statiniais metodais, net ir tais nariais, kurie yra deklaruoti privatus. Norėdami parodyti, 1 sąrašas skelbia EnclosingClass su lizdais SMClass.

Sąrašas 1. Statinės narių klasės deklaravimas (EnclosingClass.java, 1 versija)

 class EnclosingClass {private static String s; privati ​​statinė tuštuma m1 () {System.out.println (s); } static void m2 () {SMClass.accessEnclosingClass (); } static class SMClass {static void accessEnclosingClass () {s = "Skambinta iš SMClass's accessEnclosingClass () metodo"; m1 (); } void accessEnclosingClass2 () {m2 (); }}} 

1 sąrašas skelbia aukščiausio lygio klasę, pavadintą EnclosingClass su klasės lauku s, klasės metodai m1 () ir m2 ()ir statinio nario klasė SMClass. „SMClass“ deklaruoja klasės metodą accessEnclosingClass () ir egzemplioriaus metodas accessEnclosingClass2 (). Atkreipkite dėmesį į šiuos dalykus:

  • m2 ()iškviečia „SMClass“'s accessEnclosingClass () metodas reikalauja SMClass. priešdėlis, nes accessEnclosingClass () yra deklaruojamas statinis.
  • accessEnclosingClass () gali prieiti EnclosingClass's s lauką ir paskambinkite jam m1 () metodas, nors abu buvo deklaruoti privatus.

2 sąraše pateikiamas šaltinio kodas SMCDemo programos klasė, kuri parodo, kaip iškviesti SMClass's accessEnclosingClass () metodas. Tai taip pat parodo, kaip akimirksniu „SMClass“ ir pasikvieskite jį accessEnclosingClass2 () egzemplioriaus metodas.

2. sąrašas. Statinio nario klasės metodų iškvietimas (SMCDemo.java)

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

Kaip parodyta 2 sąraše, jei norite iškviesti aukščiausio lygio klasės metodą uždaroje klasėje, prieš pridėtos klasės pavadinimą turite nurodyti jį uždarančios klasės pavadinimą. Lygiai taip pat, norėdami supaprastinti uždarą klasę, turite pažymėti tos klasės pavadinimą prieš ją įtraukiančios klasės pavadinimu. Tada galite pasinaudoti egzemplioriaus metodu įprastu būdu.

Sudarykite 1 ir 2 sąrašus taip:

 javac * .java 

Kai sudarote uždarą klasę, kurioje yra statinė nario klasė, kompiliatorius sukuria klasės failą statinei narių klasei, kurios pavadinimą sudaro jos uždaromos klasės pavadinimas, dolerio ženklo simbolis ir statinio nario klasės pavadinimas. Šiuo atveju sudarant rezultatus EnclosingClass $ SMCClass.class ir EnclosingClass.class.

Paleiskite programą taip:

 java SMCDemo 

Turėtumėte stebėti šį rezultatą:

 Skambinta iš metodo „SMClass“ accessEnclosingClass (). Skambinta iš metodo „SMClass“ accessEnclosingClass () 

Pavyzdys: statinės klasės ir „Java 2D“

„Java“ standartinės klasės biblioteka yra vykdymo laiko klasės failų biblioteka, kurioje saugomos sukompiliuotos klasės ir kiti nuorodų tipai. Bibliotekoje yra daugybė statinių narių klasių pavyzdžių, kai kurie iš jų yra Java 2D geometrinių figūrų klasėse, esančiose java.awt.geom pakuotė. (Apie paketus sužinosite kitame „Java 101“ pamoka.)

Elipsė2D klasė rasta java.awt.geom apibūdina elipsę, kurią apibrėžia rėminantis stačiakampis (x, y) viršutiniame kairiajame kampe kartu su pločio ir aukščio apimtimis. Šis kodo fragmentas rodo, kad šios klasės architektūra yra pagrįsta Plūdė ir Dvigubai statinės narių klasės, kurios abi paklasės Elipsė2D:

 public abstract class Ellipse2D tęsiasi RectangularShape {viešoji statinė klasė Float tęsiasi Ellipse2D padargai 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; } // papildomų egzempliorių metodai} public static class Double pratęsia Ellipse2D padargus 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; } // papildomų egzempliorių metodai} viešasis loginis elementas yra (dvigubas x, dvigubas y) {// ...} // papildomi egzempliorių metodai, kuriuos bendrina „Float“, „Double“ ir kiti // „Ellipse2D“ poklasiai} 

Plūdė ir Dvigubai klasės tęsiasi Elipsė2D, suteikiantis slankiojo kablelio ir dvigubo tikslumo slankiojo kablelio Elipsė2D įgyvendinimai. Kūrėjai naudoja Plūdė sumažinti atminties suvartojimą, ypač todėl, kad norint sukurti vieną 2D sceną gali prireikti tūkstančių ar daugiau šių objektų. Mes naudojame Dvigubai kai reikalingas didesnis tikslumas.

Negalite akimirksniu abstrakčios Elipsė2D klasę, bet jūs galite iš karto Plūdė arba Dvigubai. Jūs taip pat galite pratęsti Elipsė2D apibūdinti pasirinktinę formą, pagrįstą elipsė.

Tarkime, kad norite pristatyti a Circle2D klasė, kurios nėra java.awt.geom pakuotė. Šis kodo fragmentas parodo, kaip sukursite Elipsė2D objektas su slankiojo kablelio įgyvendinimu:

 „Ellipse2D e2d“ = naujas „Ellipse2D.Float“ (10,0f, 10,0f, 20,0f, 30,0f); 

Kitas kodo fragmentas parodo, kaip sukursite Elipsė2D objektas su dvigubo tikslumo slankiojo kablelio įgyvendinimu:

 „Ellipse2D e2d“ = naujas „Ellipse2D.Double“ (10,0, 10,0, 20,0, 30,0); 

Dabar galite pasinaudoti bet kuriuo iš metodų, deklaruotų Plūdė arba Dvigubai pasinaudodamas grąžinimo metodu Elipsė2D nuoroda (pvz., e2d.getX ()). Tokiu pačiu būdu galite pasinaudoti bet kuriuo iš bendrų metodų Plūdė ir Dvigubaiir kurie yra deklaruoti Elipsė2D. Pavyzdys:

 e2d. yra (2.0, 3.0) 

Tai baigia statinių narių klasių įvadą. Toliau apžvelgsime vidines klases, kurios yra nestatinės narių klasės, vietinės klasės arba anoniminės klasės. Sužinosite, kaip dirbti su visais trim vidinės klasės tipais.

atsisiųsti Gauti kodą Atsisiųskite šios pamokos pavyzdžių šaltinio kodą. Sukūrė Jeffas Friesenas, skirtas „JavaWorld“.

Vidinės klasės, 1 tipas: Nestatinės narių klasės

Jūs jau anksčiau išmokote „Java 101“ serija, kaip paskelbti ne statinius (egzempliorių) laukus, metodus ir konstruktorius klasės nariais. Taip pat galite deklaruoti nestatinės narių klasės, kurios yra įdėtos ne statinės klasės, kurias deklaruojate tame pačiame lygyje kaip egzempliorių laukai, metodai ir konstruktoriai. Apsvarstykite šį pavyzdį:

 C klasė {int f; tuštuma m () {} C () {f = 2; } D klasė {// nariai}} 

Čia pristatome aukščiausio lygio klasę C su egzemplioriaus lauku f, egzemplioriaus metodas m (), konstruktoriaus ir nestatinės narių klasės D. Visi šie subjektai yra klasės nariai C, kuris juos uždaro. Tačiau, skirtingai nei ankstesniame pavyzdyje, šie egzempliorių subjektai yra susieti su atvejųC o ne su C pati klasė.

Kiekvienas nestatinės narių klasės egzempliorius yra netiesiogiai susietas su ją apimančios klasės egzemplioriumi. Nestatinių narių klasės egzempliorių metodai gali iškviesti uždaromos klasės egzempliorių metodus ir pasiekti jo egzempliorių laukus. Norėdami parodyti šią prieigą, 3 sąraše skelbiama EnclosingClass su lizdais NSMClass.

Sąrašas 3. Paskelbkite uždarą klasę su įterpta nestatine narių klase („EnclosingClass.java“, 2 versija)

 class EnclosingClass {private String s; private void m () {System.out.println (s); } klasė NSMClass {void accessEnclosingClass () {s = "Skambinta iš NSMClass metodo accessEnclosingClass ()"; m (); }}} 

3 sąraše skelbiama aukščiausio lygio klasė, pavadinta EnclosingClass su egzemplioriaus lauku s, egzemplioriaus metodas m ()ir nestatinė narių klasė NSMClass. Be to, NSMClass deklaruoja egzemplioriaus metodą accessEnclosingClass ().

Nes accessEnclosingClass () yra nestatiškas, NSMClass turi būti išaiškinta prieš pradedant taikyti šį metodą. Šis pavyzdys turi vykti per EnclosingClass, kaip parodyta 4 sąraše.

Sąrašas 4. NSMCDemo.java

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

4 sąrašas pagrindinis () metodas pirmiausia akimirksniu EnclosingClass ir išsaugo nuorodą vietiniame kintamajame ek. pagrindinis () metodas tada naudoja EnclosingClass nuoroda kaip priešdėlis į naujas operatorius, norėdamas nedelsdamas NSMClass. NSMClass nuoroda naudojama paskambinti accessEnclosingClass ().

Ar turėčiau naudoti „naujas“ su nuoroda į pridedamą klasę?

Priešdėlis naujas su nuoroda į uždarymo klasę yra reta. Vietoj to paprastai paskambinsite uždaros klasės konstruktoriumi iš konstruktoriaus arba jo uždaromos klasės egzemplioriaus metodo.

Sudarykite 3 ir 4 sąrašus taip:

 javac * .java 

Kai sudarote uždarą klasę, kurioje yra ne statinė narių klasė, kompiliatorius sukuria klasės failą ne statinei narių klasei, kurios pavadinimą sudaro jos uždarančios klasės pavadinimas, dolerio ženklo simbolis ir ne statinio nario klasės vardas. Šiuo atveju sudarant rezultatus EnclosingClass $ NSMCClass.class ir EnclosingClass.class.

Paleiskite programą taip:

 java NSMCDemo 

Turėtumėte stebėti šį rezultatą:

 Paskambinta iš „NSMClass“ metodo „accessEnclosingClass ()“ 

Kada (ir kaip) kvalifikuoti „tai“

Uždaros klasės kodas gali gauti nuorodą į jos uždaromos klasės egzempliorių, kvalifikuodamas rezervuotą žodį tai su pridedamu klasės pavadinimu ir nario prieigos operatoriumi (.). Pvz., Jei kodas yra accessEnclosingClass () reikia gauti nuorodą į jo EnclosingClass pavyzdžiui, ji nurodytų EnclosingClass.tai. Kadangi kompiliatorius sugeneruoja kodą šiai užduočiai atlikti, nurodyti šį priešdėlį yra reta.

Pavyzdys: nestatinės narių klasės „HashMap“

Į standartinę klasių biblioteką įeina ne statinės, bet ir statinės narių klasės. Šiame pavyzdyje apžvelgsime „HashMap“ klasė, kuri yra Java rinkinių sistemos dalis java.util pakuotė. „HashMap“, kuris apibūdina maišos lentele pagrįstą žemėlapio įgyvendinimą, apima keletą nestatinių narių klasių.

Pavyzdžiui, Raktų rinkinys nestatinė narių klasė apibūdina rinkinį vaizdas raktų, esančių žemėlapyje. Šis kodo fragmentas susijęs su pridedamu Raktų rinkinys klasę į jos HashMap uždara klasė:

 viešoji klasė „HashMap“ išplečia „AbstractMap“ įrankius „Map, Cloneable, Serializable“ {// įvairių narių galutinė klasė „KeySet“ išplečia „AbstractSet“ {// įvairūs nariai} // įvairūs nariai} 

ir sintaksės yra pavyzdžiai generiniai vaistai, susijusių kalbų funkcijų rinkinys, padedantis kompiliatoriui užtikrinti tipo saugumą. Pristatysiu generinius vaistus artimiausiu metu „Java 101“ pamoka. Kol kas jūs tiesiog turite žinoti, kad šios sintaksės padeda kompiliatoriui užtikrinti pagrindinių objektų, kuriuos galima išsaugoti žemėlapyje ir raktų rinkinyje, tipą ir vertės objektų, kuriuos galima išsaugoti žemėlapyje, tipą.

HashMap numato a raktų rinkinys () akimirksniu metodas Raktų rinkinys kai reikia ir grąžina šį arba talpykloje esantį egzempliorių. Čia yra visas metodas: