Klon (metoda Java) - Clone (Java method)

klon () je metoda v Programovací jazyk Java pro duplikace objektu. V Javě jsou objekty manipulovány prostřednictvím referenčních proměnných a pro operátor neexistuje žádný operátor kopírování objekt — operátor přiřazení duplikuje referenci, ne objekt. Metoda clone () poskytuje tuto chybějící funkci.

Přehled

Třídy, které chtějí kopírovací funkce, musí k tomu implementovat nějakou metodu. Do jisté míry tuto funkci poskytuje „Object.clone ()".

klon () chová se jako konstruktor kopie. Typicky to volá klon () metoda své nadtřídy k získání kopie atd., dokud nakonec nedosáhne Objektje klon () metoda. Speciální klon () metoda v základní třída Objekt poskytuje standardní mechanismus pro duplikování objektů.

The třída Objektje klon () metoda vytvoří a vrátí kopii objektu se stejnou třídou a se všemi poli se stejnými hodnotami. Nicméně, Object.clone () hodí a CloneNotSupportedException pokud objekt není instancí třídy, která implementuje značkovací rozhraní Cloneable.

Výchozí implementace Object.clone () provádí a mělká kopie. Když třída touží a hluboká kopie nebo jiné vlastní chování, musí to implementovat ve svém vlastním klon () poté, co získali kopii ze supertřídy.

Syntaxe pro volání klon v Javě je (za předpokladu obj je proměnná typu třídy, která má public klon () metoda):

Objekt kopírovat = obj.klon();

nebo běžně

Moje třída kopírovat = (Moje třída) obj.klon();

který poskytuje obsadit potřeba přiřadit generála Objekt reference vrácena z klon k odkazu na a Moje třída objekt.

Jedna nevýhoda s designem klon () metoda je, že návratový typ klon () je Objekta musí být explicitně vrženo zpět do příslušného typu. Avšak převažující klon () je vhodnější vrátit vhodný typ a eliminuje potřebu casting v klientovi (pomocí kovarianční návratové typy, od J2SE 5.0).

Další nevýhodou je, že člověk často nemá přístup k internetu klon () metoda na abstraktním typu. Většina rozhraní a abstraktních tříd v Javě neurčuje veřejnost klon () metoda. Jako výsledek, často klon () metodu lze použít pouze v případě, že je známa skutečná třída objektu, což je v rozporu s abstrakčním principem používání nejobecnějšího možného typu. Například pokud má jeden a Seznam odkaz v Javě, nelze vyvolat klon () na tomto odkazu, protože Seznam neurčuje žádnou veřejnost klon () metoda. Skutečné implementace Seznam jako ArrayList a Spojový seznam všichni obecně mají klon () samotné metody, ale je nepohodlné a špatné abstrakce nosit skutečný typ třídy objektu.

Alternativy

Existují alternativy k klon (), zejména použití a kopírovací konstruktor - konstruktor, který jako parametr přijímá jinou instanci stejné třídy - nebo tovární metoda. Tyto metody nejsou vždy adekvátní, pokud není předem znám konkrétní typ klonovaného objektu. (Nicméně, klon () často není adekvátní ani ze stejného důvodu, protože většina abstraktních tříd neimplementuje veřejnost klon () metoda.)

Alternativou k použití klonu je také použití serializace a deserializace.

Singleton vzor

Při psaní kurzu pomocí Singleton vzor, najednou může existovat pouze jedna instance této třídy. Výsledkem je, že třídě nesmí být dovoleno vytvořit klon. Aby se tomu zabránilo, lze přepsat klon () metoda pomocí následujícího kódu:

veřejnost Objekt klon() hodí CloneNotSupportedException {    házet Nový CloneNotSupportedException();}

To je nutné pouze v případě, že nadtřída implementuje veřejnost klon () nebo zabránit tomu, aby podtřída používala tuto třídu klon () způsob získání kopie. Třídy obvykle nedědí veřejnost klon () metoda protože Objekt nemá veřejnost klon () metoda, takže je obvykle zbytečné explicitně implementovat nefunkční klon () metoda.

Hierarchie tříd

Chcete-li poskytnout správně klonovatelný objekt jakéhokoli typu, musí být metoda clone () správně deklarována a správně implementována podle konvence popsané v Object.clone ().

1) Každý typ, který je třeba klonovat, musí mít ve své třídě veřejnou metodu clone () nebo metodu veřejně přístupné clone () v jedné ze svých nadřazených tříd.

Příklad:

Chcete-li vyvolat clone () na varY1, který je typu Y, pak Y nebo rodič Y musí deklarovat veřejně přístupnou metodu clone (). Tady je to nadřazená třída X, která poskytuje metodu public clone ().

veřejnost třída X nářadí Cloneable {        veřejnost X klon() hodí CloneNotSupportedException {                vrátit se (X) super.klon();        }}veřejnost třída Y rozšiřuje X { }veřejnost třída Z rozšiřuje Y { }veřejnost třída test1 {        veřejnost prázdnota funkce() hodí CloneNotSupportedException {                Y varY1 = Nový Z();                Y varY2 = (Y) varY1.klon();        }}

2) Každá třída, která implementuje clone (), by měla volat super.clone (), aby získala odkaz na klonovaný objekt. Pokud má třída jakékoli odkazy na objekty, které musí být také klonovány (například při hlubokém kopírování), měla by metoda clone () provést všechny požadované úpravy objektu před jeho vrácením. (Protože Object.clone () vrací přesnou kopii původního objektu, veškerá proměnlivá pole, jako jsou kolekce a pole, by byla sdílena mezi originálem a kopií - což by ve většině případů nebylo ani očekáváno, ani žádoucí.)

Příklad:

Protože třída Z obsahuje odkaz na objekt, její metoda clone () také klonuje tento odkaz na objekt, aby vrátila hlubokou kopii originálu.

veřejnost třída X nářadí Cloneable {        veřejnost X klon() hodí CloneNotSupportedException {                vrátit se (X) super.klon();        }}veřejnost třída Y rozšiřuje X { }veřejnost třída ObjectABC nářadí Cloneable {        veřejnost ObjectABC klon() hodí CloneNotSupportedException {                vrátit se (ObjectABC) super.klon();        }}veřejnost třída Z rozšiřuje Y {        soukromé ObjectABC některéABC;        veřejnost Z klon() hodí CloneNotSupportedException {                Z novýZ = (Z) super.klon();                novýZ.některéABC = některéABC.klon();                vrátit se novýZ;        }}veřejnost třída test1 {        veřejnost prázdnota funkce() hodí CloneNotSupportedException {                Y varY1 = Nový Z();                Y varY2 = (Y) varY1.klon();        }}

Úskalí

Pokud každá třída v hierarchii implementuje a klon () metoda, všechny tyto funkce budou vyvolány při klonování a přidáním nějaké režie. Během mnoha iterací by se tato režie mohla stát významnou.

U grafů složitých objektů může být hluboké kopírování také problematické, pokud existují rekurzivní odkazy.

Není vždy vhodné mít kolem sebe více kopií stejného objektu. Pokud je účel konkrétního klon () implementace není plně pochopena spotřebiteli, může neúmyslně narušit paradigma „jeden objekt, více odkazů“.

Závěrečná pole

Obvykle, klon () je nekompatibilní s finále pole. Protože klon () je v podstatě výchozí konstruktor (ten, který nemá žádné argumenty), je nemožné přiřadit a finále pole v rámci klon () metoda; výsledkem je chyba kompilátoru. Kde je hodnota pole an neměnný objekt to je v pořádku; jen nechte 'konstruktor' zkopírovat odkaz a originál i jeho klon budou sdílet stejný objekt.

Ale kde je hodnota proměnlivý objekt, musí být hluboce zkopírován. Jedním z řešení je odstranění finále modifikátor z pole, vzdávající se výhod, které mu modifikátor udělil.

Z tohoto důvodu někteří programátoři navrhují vytvořit objekty v hierarchii Serializovatelné a vytvářet kopie serializací starého objektu a poté vytvořením nového objektu z výsledného bitový proud, který zpracovává konečné datové členy správně, ale je výrazně pomalejší.[1]

Alternativně lze z aktuálních polí objektů vrátit zcela nový objekt, který lze provést nejprve voláním konstruktoru a později přiřazením ne finálních polí. Další alternativní metodou je ve skutečnosti formalizace myšlenky: vytvoření konstruktoru kopie, který přebírá instanci. To je ve skutečnosti to, co někteří lidé doporučují při klonování.[2]

Reference

  1. ^ Miller, Dave (6. srpna 1999). „Java Tip 76: Alternativa k technice hlubokého kopírování“. JavaWorld. Citováno 2020-07-14.
  2. ^ Clone () vs Copy konstruktor - který se doporučuje v Javě, Přetečení zásobníku

externí odkazy