Nezmeniteľné objekty v Jave

1. Prehľad

V tomto tutoriále sa dozvieme, čo robí objekt nemenným, ako dosiahnuť nemennosť v Jave a aké výhody s tým prináša.

2. Čo je to nemenný objekt?

Nemenný objekt je objekt, ktorého vnútorný stav zostane po úplnom vytvorení konštantný.

To znamená, že verejné API nemenného objektu nám zaručuje, že sa bude správať rovnako počas celej svojej životnosti.

Keď sa pozrieme na triedu String, môžeme vidieť, že aj keď sa zdá, že jeho API poskytuje svoje premenlivé správanie vymeniť metóda, originál String nemení sa:

Názov reťazca = "baeldung"; Reťazec newName = name.replace ("trus", "----"); assertEquals ("baeldung", meno); assertEquals ("bael ----", newName);

API nám poskytuje metódy iba na čítanie, nikdy by nemalo obsahovať metódy, ktoré menia interný stav objektu.

3. The konečné Kľúčové slovo v Jave

Predtým, ako sa pokúsime dosiahnuť nemennosť v Jave, mali by sme sa rozprávať o konečné kľúčové slovo.

V Jave premenné sú predvolene zmeniteľné, čo znamená, že môžeme zmeniť ich hodnotu.

Použitím konečné kľúčové slovo pri deklarácii premennej, kompilátor Java nám nedovolí zmeniť hodnotu tejto premennej. Namiesto toho nahlási chybu pri kompilácii:

konečný názov reťazca = "baeldung"; name = "bael ...";

Poznač si to konečné zakazuje nám iba zmenu referencie, ktorú má premenná, nechráni nás pred zmenou interného stavu objektu, na ktorý odkazuje, pomocou jeho verejného API:

posledné zoznamové reťazce = nový ArrayList (); assertEquals (0, strings.size ()); strings.add ("baeldung"); assertEquals (0, strings.size ());

Druhy assertEquals zlyhá, pretože pridaním prvku do zoznamu sa zmení jeho veľkosť, nejde teda o nemenný objekt.

4. Nemeniteľnosť v Jave

Teraz, keď vieme, ako sa vyhnúť zmenám v obsahu premennej, môžeme ju použiť na zostavenie API nemenných objektov.

Budovanie API nemenného objektu si vyžaduje, aby sme zaručili, že sa jeho vnútorný stav nezmení bez ohľadu na to, ako jeho API použijeme.

Krokom správnym smerom je použitie konečné pri deklarácii jeho atribútov:

trieda Peniaze {súkromná konečná dvojnásobná suma; súkromná konečná mena; // ...}

Upozorňujeme, že Java nám zaručuje, že hodnota čiastka sa nezmení, to je prípad všetkých premenných primitívneho typu.

V našom príklade máme však iba záruku, že: mena nezmení sa, takže musíme sa spoľahnúť na Mena API sa chrániť pred zmenami.

Väčšinou potrebujeme, aby atribúty objektu obsahovali vlastné hodnoty, a miestom na inicializáciu vnútorného stavu nemenného objektu je jeho konštruktor:

trieda Peniaze {// ... verejné peniaze (dvojnásobná suma, mena meny) {this.amount = suma; this.currency = currency; } public Currency getCurrency () {návratová mena; } verejné zdvojnásobenie getAmount () {návratná čiastka; }}

Ako sme už povedali, aby sme splnili požiadavky nemenného rozhrania API, naše Peniaze trieda má iba metódy iba na čítanie.

Pomocou reflexného API dokážeme prelomiť nemennosť a meniť nemenné objekty. Odraz však porušuje verejné API nemenného objektu a zvyčajne by sme sa tomu mali vyhnúť.

5. Výhody

Pretože vnútorný stav nemenného objektu zostáva v čase konštantný, môžeme to bezpečne zdieľať medzi viacerými vláknami.

Môžeme ho tiež slobodne používať a môžeme povedať, že žiadny z objektov, na ktoré sa odkazuje, nezistí žiadny rozdiel nemenné objekty sú vedľajšie účinky zdarma.

6. Záver

Nezmeniteľné objekty nemenia svoj vnútorný stav v čase, sú bezpečné pre vlákna i bez vedľajších účinkov. Kvôli týmto vlastnostiam sú nemenné objekty tiež obzvlášť užitočné pri práci s prostrediami viacerých vlákien.

Príklady použité v tomto článku nájdete na serveri GitHub.