Vnorené triedy v Jave

1. Úvod

Tento tutoriál predstavuje rýchly a podrobný úvod do vnorených tried v jazyku Java.

Jednoducho povedané, Java nám umožňuje definovať triedy v rámci iných tried. Vnorené triedy nám umožňujú logicky zoskupiť triedy, ktoré sa používajú iba na jednom mieste, napísať čitateľnejší a udržiavateľnejší kód a zvýšiť zapuzdrenie.

Skôr ako začneme, pozrime sa na niekoľko typov vnorených tried dostupných v jazyku:

  • Statické vnorené triedy
  • Nestatické vnorené triedy
  • Miestne triedy
  • Anonymné triedy

V ďalších častiach sa budeme podrobne venovať každej z nich.

2. Statické vnorené triedy

Tu je niekoľko vecí, ktoré treba pamätať na statické vnorené triedy:

  • Rovnako ako statické členy, aj tieto patria do ich uzatvárajúcej triedy, a nie do inštancie triedy
  • Vo svojej deklarácii môžu mať všetky typy modifikátorov prístupu
  • Majú prístup iba k statickým členom v priloženej triede
  • Môžu definovať statické aj nestatické členy

Pozrime sa, ako môžeme deklarovať statickú vnorenú triedu:

public class Enclosing {private static int x = 1; public static class StaticNested {private void run () {// method implementation}} @Test public void test () {Enclosing.StaticNested nested = new Enclosing.StaticNested (); nested.run (); }}

3. Nestatické vnorené triedy

Ďalej uvádzam niekoľko rýchlych bodov, ktoré si treba pamätať o nestatických vnorených triedach:

  • Hovorí sa im aj vnútorné triedy
  • Vo svojej deklarácii môžu mať všetky typy modifikátorov prístupu
  • Rovnako ako premenné inštancie a metódy, aj vnútorné triedy sú spojené s inštanciou priloženej triedy
  • Majú prístup ku všetkým členom priloženej triedy bez ohľadu na to, či sú statickí alebo nestatickí
  • Môžu definovať iba nestatické členy

Takto môžeme vyhlásiť vnútornú triedu:

verejná trieda Vonkajšia {verejná trieda Vnútorná {// ...}}

Ak deklarujeme vnorenú triedu s modifikátorom statický, potom je to statický člen. Inak je to vnútorná trieda. Aj keď syntakticky je rozdiel iba jedným kľúčovým slovom (t. J. statický), sémanticky existuje obrovský rozdiel medzi týmito druhmi vnorených tried. Inštancie vnútornej triedy sú viazané na obklopujúce triedy, a preto majú prístup k svojim členom. Mali by sme si byť vedomí tohto problému pri výbere, či má byť vnorená trieda vnútornou.

Na vytvorenie inštancie vnútornej triedy musíme najskôr vytvoriť inštanciu jej uzatvárajúcej triedy.

Pozrime sa, ako to môžeme urobiť:

Vonkajší vonkajší = nový Vonkajší (); Vonkajší. Vnútorný vnútorný = vonkajší. Nový vnútorný ();

V nasledujúcich podkapitolách si ukážeme niektoré špeciálne typy vnútorných tried.

3.1. Miestne triedy

Miestne triedy sú špeciálnym typom vnútorných tried - v ktorých trieda je definovaná vo vnútri metódy alebo blok rozsahu.

Pozrime sa na niekoľko bodov, ktoré si treba pamätať o tomto type triedy:

  • Vo svojom vyhlásení nemôžu mať modifikátory prístupu
  • Majú prístup k statickým aj nestatickým členom v priloženom kontexte
  • Môžu definovať iba členov inštancie

Tu je rýchly príklad:

public class NewEnclosing {void run () {class Local {void run () {// method implementation}} Local local = new Local (); local.run (); } @Test public void test () {NewEnclosing newEnclosing = new NewEnclosing (); newEnclosing.run (); }}

3.2. Anonymné triedy

Anonymné triedy možno použiť na definovanie implementácie rozhrania alebo abstraktnej triedy bez toho, aby ste museli vytvárať opakovane použiteľnú implementáciu.

Uveďme niekoľko bodov, ktoré si treba pamätať o anonymných triedach:

  • Vo svojom vyhlásení nemôžu mať modifikátory prístupu
  • Majú prístup k statickým aj nestatickým členom v priloženom kontexte
  • Môžu definovať iba členov inštancie
  • Sú jediným typom vnorených tried, ktoré nedokážu definovať konštruktory ani rozširovať / implementovať ďalšie triedy alebo rozhrania

Ak chcete definovať anonymnú triedu, najskôr si zadefinujeme jednoduchú abstraktnú triedu:

abstraktná trieda SimpleAbstractClass {abstrakt void run (); }

Teraz sa pozrime, ako môžeme definovať anonymnú triedu:

public class AnonymousInnerUnitTest {@Test public void whenRunAnonymousClass_thenCorrect () {SimpleAbstractClass simpleAbstractClass = new SimpleAbstractClass () {void run () {// implementácia metódy}}; simpleAbstractClass.run (); }}

Ak sa chcete dozvedieť viac podrobností, môže sa nám hodiť náš tutoriál Anonymous Classes in Java.

4. Tienenie

Vyhlásenie členov vnútornej triedy je v tieni deklarácie priloženej triedy ak majú rovnaké meno.

V takom prípade toto kľúčové slovo odkazuje na inštancie vnorenej triedy a na členov vonkajšej triedy možno odkazovať pomocou názvu vonkajšej triedy.

Pozrime sa na krátky príklad:

verejná trieda NewOuter {int a = 1; statický int b = 2; verejná trieda InnerClass {int a = 3; statický konečný int b = 4; public void run () {System.out.println ("a =" + a); System.out.println ("b =" + b); System.out.println ("NewOuterTest.this.a =" + NewOuter.this.a); System.out.println ("NewOuterTest.b =" + NewOuter.b); System.out.println ("NewOuterTest.this.b =" + NewOuter.this.b); }} @Test public void test () {NewOuter vonkajší = nový NewOuter (); NewOuter.InnerClass vnútorný = vonkajší. Nová InnerClass (); vnútorný.beh (); }}

5. Serializácia

Aby sa zabránilo a java.io.NotSerializableException pri pokuse o serializáciu vnorenej triedy by sme mali:

  • Vyhlásiť vnorenú triedu za statický
  • Vytvorte implementáciu vnorenej triedy aj priloženej triedy Serializovateľné

6. Záver

V tomto článku sme videli, čo sú vnorené triedy a ich rôzne typy. Pozreli sme sa tiež na to, ako sa modifikátory viditeľnosti a prístupu v teréne líšia medzi týmito rôznymi typmi.

Celú implementáciu tohto tutoriálu nájdete ako vždy na GitHub.