Programovanie

Inicializácia triedy a objektu v Jave

Triedy a objekty v Jave musia byť pred použitím inicializované. Už ste sa predtým dozvedeli, že polia tried sa pri načítaní tried inicializujú na predvolené hodnoty a že objekty sa inicializujú prostredníctvom konštruktorov, ale v inicializácii je toho viac. Tento článok predstavuje všetky funkcie Java na inicializáciu tried a objektov.

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

Ako inicializovať triedu Java

Predtým, ako preskúmame podporu Java pre inicializáciu triedy, poďme si zopakovať kroky inicializácie triedy Java. Zvážte zoznam 1.

Zoznam 1. Inicializácia polí triedy na predvolené hodnoty

trieda SomeClass {static boolean b; statický bajt podľa; statický znak c; statické dvojité d; statický plavák f; statický int i; statický dlhý l; statické krátke s; statický Reťazec st; }

Výpis 1 deklaruje triedu SomeClass. Táto trieda deklaruje deväť polí typov boolean, bajt, char, dvojitý, plavák, int, dlho, krátkya String. Kedy SomeClass je načítaná, bity každého poľa sú nastavené na nulu, čo interpretujete nasledovne:

false 0 \ u0000 0,0 0,0 0 0 0 null

Predchádzajúce polia triedy boli implicitne inicializované na nulu. Môžete však tiež explicitne inicializovať polia triedy priamym priradením hodnôt k nim, ako je uvedené v zozname 2.

Zoznam 2. Inicializácia polí triedy na explicitné hodnoty

trieda SomeClass {static boolean b = true; statický bajt o = 1; static char c = 'A'; statické dvojité d = 2,0; statický plavák f = 3,0f; statický int i = 4; statický dlhý l = 5000000000L; statické krátke s = 20 000; statický reťazec st = "abc"; }

Hodnota každej úlohy musí byť typovo kompatibilná s typom poľa triedy. Každá premenná ukladá hodnotu priamo, s výnimkou sv. Variabilné sv ukladá odkaz na a String objekt, ktorý obsahuje abc.

Odkazy na polia triedy

Pri inicializácii poľa triedy je legálne inicializovať ho na hodnotu predtým inicializovaného poľa triedy. Napríklad zoznam 3 sa inicializuje r do Xhodnota. Obe polia sú inicializované na 2.

Zoznam 3. Odkaz na predtým deklarované pole

trieda SomeClass {static int x = 2; statický int y = x; public static void main (String [] args) {System.out.println (x); System.out.println (y); }}

Opak však nie je legálny: pole triedy nemôžete inicializovať na hodnotu následne deklarovaného poľa triedy. Výstupy kompilátora Java nezákonný odkaz na ďalší odkaz keď narazí na tento scenár. Zvážte zoznam 4.

Zoznam 4. Pokus o odkaz na následne deklarované pole

trieda SomeClass {static int x = y; statický int y = 2; public static void main (String [] args) {System.out.println (x); System.out.println (y); }}

Kompilátor bude hlásiť nezákonný odkaz na odoslanie keď sa stretne statický int x = y;. Je to tak preto, lebo zdrojový kód sa kompiluje zhora nadol a kompilátor ho ešte nevidel r. (Túto správu by tiež odoslalo, keby r nebol výslovne inicializovaný.)

Inicializačné bloky triedy

V niektorých prípadoch možno budete chcieť vykonať zložité inicializácie založené na triedach. Urobíte to po načítaní triedy a pred vytvorením akýchkoľvek objektov z tejto triedy (za predpokladu, že trieda nie je úžitkovou triedou). Pre túto úlohu môžete použiť inicializačný blok triedy.

A inicializačný blok triedy je blok vyhlásení, pred ktorým je statický kľúčové slovo, ktoré sa zavádza do tela triedy. Po načítaní triedy sa tieto príkazy vykonajú. Zvážte zoznam 5.

Zoznam 5. Inicializácia polí sínusových a kosínusových hodnôt

trieda Grafika {statický dvojitý [] sínus, kosínus; static {sines = nový dvojitý [360]; kosínusy = nový dvojitý [360]; for (int i = 0; i <sines.length; i ++) {sines [i] = Math.sin (Math.toRadians (i)); kosínusy [i] = Math.cos (Math.toRadians (i)); }}}

Zoznam 5 deklaruje a Grafika trieda, ktorá deklaruje sines a kosínusy premenné poľa. Deklaruje tiež inicializačný blok triedy, ktorý vytvára 360-prvkové polia, ktorých referencie sú priradené sines a kosínusy. Potom použije a pre príkaz na inicializáciu týchto prvkov poľa na príslušné sínusové a kosínusové hodnoty volaním znaku Matematika triedy hriech () a cos () metódy. (Matematika je súčasťou štandardnej knižnice triedy Java. Tejto triede a týmto metódam sa budem venovať v budúcom článku.)

Výkonový trik

Pretože výkon je pre grafické aplikácie dôležitý a pretože je rýchlejšie získať prístup k prvku poľa ako volať metódu, vývojári sa uchyľujú k výkonnostným trikom, ako je vytváranie a inicializácia polí sínusov a kosínusov.

Kombinácia inicializátorov poľa triedy a blokov inicializácie triedy

V aplikácii môžete kombinovať viac inicializátorov poľa triedy a blokov inicializácie triedy. Výpis 6 poskytuje príklad.

Zoznam 6. Prebieha inicializácia triedy v poradí zhora nadol

trieda MCFICIB {static int x = 10; statická dvojnásobná teplota = 98,6; static {System.out.println ("x =" + x); teplota = (teplota - 32) * 5,0 / 9,0; // prevádzať na Celzia System.out.println ("temp =" + temp); } statický int y = x + 5; static {System.out.println ("y =" + y); } public static void main (reťazec [] args) {}}

Výpis 6 deklaruje a inicializuje pár polí triedy (X a r) a vyhlasuje dvojicu statický inicializátory. Zostavte tento záznam podľa obrázka:

javac MCFICIB.java

Potom spustite výslednú aplikáciu:

java MCFICIB

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

x = 10 tepl. = 37,0 r = 15

Tento výstup ukazuje, že inicializácia triedy sa vykonáva v poradí zhora nadol.

() metódy

Pri kompilácii inicializátorov triedy a blokov inicializácie triedy kompilátor Java ukladá skompilovaný bytecode (v poradí zhora nadol) špeciálnou metódou s názvom (). Uhlové konzoly bránia a konflikt mien: nemôžete vyhlásiť a () metóda v zdrojovom kóde, pretože < a > znaky sú v kontexte identifikátora nelegálne.

Po načítaní triedy JVM pred zavolaním zavolá túto metódu hlavný() (kedy hlavný() je prítomný).

Poďme sa pozrieť dovnútra MCFICIB.trieda. Nasledujúca čiastočná demontáž odhalí uložené informácie pre server X, tepla r polia:

Pole č. 1 00000290 Prístupové príznaky ACC_STATIC 00000292 Názov x 00000294 Deskriptor I 00000296 Počet atribútov 0 Pole č. 2 00000298 Prístupové príznaky ACC_STATIC 0000029a Teplota tepl. 0000029c Deskriptor D 0000029e Atribúty Počet 0 Pole # 3 000002a0 Prístupové príznaky ACC_STATIC 000002a2 0

The Deskriptor riadok identifikuje JVM deskriptor typu pre pole. Typ je reprezentovaný jedným písmenom: Ja pre int a D pre dvojitý.

Nasledujúca čiastočná demontáž odhaľuje postupnosť inštrukcií bytecode pre () metóda. Každý riadok začína desatinným číslom, ktoré identifikuje nulovú adresu offsetu nasledujúcej inštrukcie:

 0 bipush 10 2 putstatic MCFICIB / x I 5 ldc2_w # 98.6 8 putstatic MCFICIB / temp D 11 getstatic java / lang / System / out Ljava / io / PrintStream; 14 nových java / lang / StringBuilder 17 dup 18 vyvoláva špeciálne java / lang / StringBuilder / () V 21 ldc "x =" 23 invokevirtual java / lang / StringBuilder / append (Ljava / lang / String;) Ljava / lang / StringBuilder; 26 getstatic MCFICIB / x I 29 invokevirtual java / lang / StringBuilder / append (I) Ljava / lang / StringBuilder; 32 invokevirtual java / lang / StringBuilder / toString () Ljava / lang / String; 35 invokevirtual java / io / PrintStream / println (Ljava / lang / String;) V 38 getstatic MCFICIB / temp D 41 ldc2_w # 32 44 dsub 45 ldc2_w # 5 48 dmul 49 ldc2_w # 9 52 ddiv 53 putstatic MCFICIB / temp D 56 getstatic java / lang / System / out Ljava / io / PrintStream; 59 nových java / lang / StringBuilder 62 dup 63 vyvoláva špeciálne java / lang / StringBuilder / () V 66 ldc "temp =" 68 invokevirtual java / lang / StringBuilder / append (Ljava / lang / String;) Ljava / lang / StringBuilder; 71 getstatic MCFICIB / temp D 74 invokevirtual java / lang / StringBuilder / append (D) Ljava / lang / StringBuilder; 77 invokevirtual java / lang / StringBuilder / toString () Ljava / lang / String; 80 invokevirtual java / io / PrintStream / println (Ljava / lang / String;) V 83 getstatic MCFICIB / x I 86 iconst_5 87 iadd 88 putstatic MCFICIB / y I 91 getstatic java / lang / System / out Ljava / io / PrintStream; 94 new java / lang / StringBuilder 97 dup 98 invokes special java / lang / StringBuilder / () V 101 ldc "y =" 103 invokevirtual java / lang / StringBuilder / append (Ljava / lang / String;) Ljava / lang / StringBuilder; 106 getstatic MCFICIB / y I 109 invokevirtual java / lang / StringBuilder / append (I) Ljava / lang / StringBuilder; 112 invokevirtual java / lang / StringBuilder / toString () Ljava / lang / String; 115 invokevirtual java / io / PrintStream / println (Ljava / lang / String;) V 118 návrat

Poradie inštrukcií od offsetu 0 do offsetu 2 je ekvivalentné s nasledujúcim inicializátorom poľa triedy:

statický int x = 10;

Poradie inštrukcií od offsetu 5 do offsetu 8 je ekvivalentné s nasledujúcim inicializátorom poľa triedy:

statická dvojnásobná teplota = 98,6;

Postupnosť inštrukcií od offsetu 11 do offsetu 80 je ekvivalentná s nasledujúcim inicializačným blokom triedy:

static {System.out.println ("x =" + x); teplota = (teplota - 32) * 5,0 / 9,0; // prevádzať na Celzia System.out.println ("temp =" + temp); }

Postupnosť inštrukcií od offsetu 83 do offsetu 88 je ekvivalentná s nasledujúcim inicializátorom poľa triedy:

statický int y = x + 5;

Postupnosť inštrukcií od offsetu 91 do offsetu 115 je ekvivalentná s nasledujúcim inicializačným blokom triedy:

static {System.out.println ("y =" + y); }

Nakoniec návrat inštrukcia na offset 118 vráti vykonanie z () do tej časti JVM, ktorá túto metódu volala.

Nerobte si starosti s tým, čo znamená bytecode

Postupom z tohto cvičenia je zistiť, že všetok kód v inicializátoroch poľa triedy 6 a blokoch inicializácie triedy sa nachádza v () metódou a vykonáva sa v poradí zhora nadol.

Ako inicializovať objekty

Po načítaní a inicializácii triedy budete často chcieť z tejto triedy vytvárať objekty. Ako ste sa dozvedeli v mojom nedávnom úvode do programovania s triedami a objektmi, inicializujete objekt pomocou kódu, ktorý umiestnite do konštruktora triedy. Zvážte zoznam 7.

Zoznam 7. Použitie konštruktora na inicializáciu objektu

trieda Mesto {súkromné ​​meno reťazca; int populácia; Mesto (názov reťazca, počet obyvateľov) {this.name = meno; this.population = populácie; } @Override public String toString () {návratové meno + ":" + populácia; } public static void main (String [] args) {City newYork = new City ("New York", 8491079); System.out.println (newYork); // Výstup: New York: 8491079}}

Zoznam 7 deklaruje a Mesto trieda s názov a populácia polia. Keď Mesto objekt je vytvorený, Mesto (názov reťazca, počet obyvateľov) Konštruktor sa volá na inicializáciu týchto polí na argumenty volaného konštruktora. (Tiež som prepísal Objektje public String toString () metóda na pohodlné vrátenie názvu mesta a hodnoty populácie ako reťazca. System.out.println () nakoniec zavolá túto metódu, aby vrátila reťazcovú reprezentáciu objektu, z ktorej vychádza.)

Predtým, ako sa zavolá konštruktor, aké hodnoty sa majú vykonať názov a populácia obsahovať? Zistíte vložením System.out.println (toto.nazov); System.out.println (this.population); na začiatku konštruktéra. Po zostavení zdrojového kódu (javac City.java) a spustenie aplikácie (mesto java), pozorovali by ste nulový pre názov a 0 pre populácia. The Nový operátor vynuluje polia objektu (inštancie) objektu pred vykonaním konštruktora.

Rovnako ako v poliach triedy, aj v tomto môžete explicitne inicializovať polia objektov. Môžete napríklad určiť Názov reťazca = "New York"; alebo int populácia = 8491079;. Spravidla však tým nie je možné nič získať, pretože tieto polia sa inicializujú v konštruktore. Jedinou výhodou, na ktorú si myslím, je priradenie predvolenej hodnoty k poľu objektu; táto hodnota sa používa, keď voláte konštruktor, ktorý neinicializuje pole:

int numDoors = 4; // predvolená hodnota pridelená numDoors Car (značka reťazca, model reťazca, int rok) {this (značka, model, rok, numDoors); } Auto (značka, model reťazca, int rok, int numDoors) {this.make = make; this.model = model; this.year = year; this.numDoors = numDoors; }

Inicializácia objektov zrkadlí inicializáciu triedy

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