Java Copy Constructor

1. Úvod

Konštruktor kópie v triede Java je konštruktor, ktorý vytvorí objekt pomocou iného objektu tej istej triedy Java.

To je užitočné, keď chceme kopírovať zložitý objekt, ktorý má niekoľko polí, alebo ak chceme vytvoriť hlbokú kópiu existujúceho objektu.

2. Ako vytvoriť kopírovací konštruktor

Aby sme vytvorili konštruktor kopírovania, môžeme najskôr deklarovať konštruktor, ktorý vezme objekt rovnakého typu ako parameter:

public class Employee {private int id; súkromné ​​meno reťazca; verejný zamestnanec (zamestnanec zamestnanca) {}}

Potom skopírujeme každé pole vstupného objektu do novej inštancie:

public class Employee {private int id; súkromné ​​meno reťazca; verejný zamestnanec (zamestnanec zamestnanca) {this.id = employee.id; this.name = employee.name; }}

To, čo tu máme, je plytká kópia, čo je v poriadku, pretože všetky naše polia - int a a String v tomto prípade - sú to buď primitívne typy, alebo nemenné typy.

Ak má trieda Java premenlivé polia, môžeme namiesto toho vytvoriť a hlboká kópia vo vnútri svojho konštruktora kópií. Pri hlbokej kópii je novovytvorený objekt nezávislý od pôvodného, ​​pretože vytvárame samostatnú kópiu každého premenlivého objektu:

public class Employee {private int id; súkromné ​​meno reťazca; súkromné ​​Dátum začiatkuDátum; verejný zamestnanec (zamestnanec zamestnanca) {this.id = employee.id; this.name = employee.name; this.startDate = nový dátum (employee.startDate.getTime ()); }}

3. Kopírujte Constructor vs. Clone

V Jave môžeme tiež použiť klon metóda na vytvorenie objektu z existujúceho objektu. Avšak konštruktor kopírovania má oproti klon metóda:

  1. Kopírovací konštruktor je oveľa ľahšie implementovateľný. Nie je potrebné implementovať Cloneable rozhranie a rukoväť CloneNotSupportedException.
  2. The klon metóda vráti všeobecný Objekt odkaz. Preto ho musíme obsadiť vhodným typom.
  3. Nemôžeme priradiť hodnotu a konečné pole v klon metóda. Môžeme to však urobiť v konštruktore kópií.

4. Problémy s dedením

Konštruktory kopírovania v Jave nie sú zdediteľné podtriedami. Preto ak sa pokúsime inicializovať podradený objekt z odkazu na nadradenú triedu, stretneme sa s castingovým problémom pri klonovaní pomocou konštruktora kópií.

Na ilustráciu tohto problému si najskôr vytvorme podtriedu Zamestnanec a jeho konštruktor kópií:

public class manager rozširuje Employee {private List directReports; // ... ostatní konštruktéri public Manager (Manager manager) {super (manager.id, manager.name, manager.startDate); this.directReports = directReports.stream () .collect (Collectors.toList ()); }} 

Potom vyhlásime Zamestnanec premenná a vytvorte jej inštanciu pomocou Manažér konštruktér:

Zdroj zamestnanca = nový manažér (1, „manažér Baeldung“, startDate, directReports);

Pretože referenčný typ je Zamestnanec, musíme to obsadiť Manažér napíšeme, aby sme mohli použiť konštruktor kopírovania Manažér trieda:

Zamestnanecký klon = nový manažér ((zdroj) (manažér));

Môžeme dostať ClassCastException za behu, ak vstupný objekt nie je inštanciou Manažér trieda.

Jedným zo spôsobov, ako sa vyhnúť castingu v konštruktore kopírovania, je vytvorenie novej dedičnej metódy pre obe triedy:

public class Employee {public Employee copy () {return new Employee (this); }} public class Manager rozširuje zamestnanca {@Override public Employee copy () {vrátiť nového manažéra (toto); }}

V každej metóde triedy nazývame jej konštruktor kópie so vstupom toto objekt. Týmto spôsobom môžeme zaručiť, že sa vygenerovaný objekt rovná objektu volajúceho:

Zamestnanecký klon = source.copy ();

5. Záver

V tomto tutoriáli sme si ukázali, ako vytvoriť konštruktor kópie, pomocou niekoľkých príkladov kódu. Diskutovali sme tiež o niekoľkých dôvodoch, prečo by sme sa mali vyhnúť klon metóda.

Konštruktor kopírovania má problém s prenášaním, keď ho použijeme na klonovanie objektu podradenej triedy, ktorého referenčným typom je nadradená trieda. Pre túto otázku sme poskytli jedno riešenie.

Ako vždy, zdrojový kód tutoriálu je k dispozícii na GitHub.