klon je přesná kopie originálu. V Javě to v podstatě znamená schopnost vytvořit objekt s podobným stavem jako původní objekt. Tuto funkci poskytuje metoda java clone()
.
v tomto příspěvku prozkoumáme většinu důležitých aspektů klonu Java.
Table of Contents1. What is clone?2. Java Cloneable interface and clone() method3. Shallow Copy4. Deep Copy5. Java Copy Constructors6. Deep copy with serialization7. Cloning using Apache commons8. Java clone best practices
co je Java clone?
takže klonování je o vytvoření kopie původního objektu. Jeho význam slovníku je : „vytvořte identickou kopii“.
ve výchozím nastavení je klonování java „pole po poli Kopírovat“, tj. protože třída objektu nemá představu o struktuře třídy, na které bude vyvolána metoda clone ().
Tak, JVM, když volal pro klonování, dělat následující věci:
- v Případě, že třída má pouze primitivní typ dat členů pak zcela novou kopii objektu bude vytvořen a odkaz na nový objekt, kopie budou vráceny.
- v Případě, že třída obsahuje členy nějaké třídy typu pak jen objekt odkazy na tyto členy jsou zkopírovány, a proto členské odkazy na původní objekt, stejně jako klonovaný objekt odkazují na tentýž objekt.
kromě výše uvedeného výchozího chování můžete toto chování vždy přepsat a zadat své vlastní. To se provádí přepsáním metody clone()
. Uvidíme, jak se to dělá.
Java Cloneable interface and clone() method
každý jazyk, který podporuje klonování objektů, má svá vlastní pravidla a stejně tak java. V Javě, pokud třída potřebuje podporovat klonování, musí dělat následující věci:
- musíte implementovat
Cloneable
rozhraní. - musíte přepsat
clone()
metodu z třídy objektů.
Přečtěte si více: rozhraní Cloneable je rozbité v javě
Java dokumenty o clone()
metody jsou uvedeny níže (ve formátu a extrahovat).
- první příkaz zaručuje, že klonovaný objekt bude mít samostatné přiřazení adresy paměti.
- druhé prohlášení naznačuje, že původní a klonované objekty by měly mít stejný typ třídy, ale není povinné.
- třetí tvrzení naznačuje, že původní a klonované objekty by měly být stejné pomocí metody equals (), ale není povinné.
pojďme pochopit Java klon s příkladem. Naše první třída je Employee
třídy s 3 atributy – id
name
department
.
Department
třída má dva atributy – id
name
.
Pokud tedy potřebujeme klonovat třídu zaměstnanců, musíme udělat něco takového.
skvělé, úspěšně jsme klonovali objekt Employee
. Nezapomeňte však, že máme dva odkazy na stejný objekt a nyní oba změní stav objektu v různých částech aplikace. Chcete vidět jak? Podívejme se.
Jejda, změny klonovaného objektu jsou viditelné i v originále. Tímto způsobem mohou klonované objekty v systému způsobit zmatek, pokud to bude povoleno. Kdokoli může přijít a klonovat vaše aplikační objekty a dělat, co se mu líbí. Můžeme tomu zabránit??
odpověď je ano, můžeme. Můžeme tomu zabránit vytvořením Java deep copy a použitím konstruktorů kopírování. Dozvíme se o nich později v tomto příspěvku. Nejprve se podívejme, co je hluboké klonování a mělké klonování v Javě.
Java Shallow Copy
Shallow clone je „výchozí implementace“ v Javě. V metodě overridden clone
, pokud klonujete všechny typy objektů (nikoli primitivy), vytváříte mělkou kopii.
Všechny výše uvedené příklady jsou mělké kopírování jen proto, že jsme se naklonoval Department
objekt na Employee
class clone
metoda. Nyní přejdu k další části, kde uvidíme hluboké klonování.
Java Deep Copy
Deep clone je ve většině případů požadovaným chováním. V hluboké kopii vytvoříme klon, který je nezávislý na původním objektu a změny v klonovaném objektu by neměly mít vliv na původní objekt.
podívejme se, jak hluboká kopie je vytvořena v Javě.
jsem upravil Employee
třídy clone()
metoda a přidal následující clone
metoda Department
třídy.
nyní testování našeho klonovacího kódu dává požadovaný výsledek a název oddělení nebude změněn.
zde změna stavu klonovaného objektu nemá vliv na původní objekt.
takže hluboké klonování vyžaduje splnění následujících pravidel –
- Není třeba samostatně kopírovat Primitiva.
- Všechny členské tříd v původní třídě by měl podporovat klonování a v clone metodu původní třídy v kontextu měli říkat
super.clone()
na všechny členské třídy. - Pokud se některý člen třídy nepodporuje klonování pak v clone metodu, musí vytvořit nové instance, že členské třídy a zkopírujte všechny jeho atributy jeden po druhém do nové členské třídy objektu. Tento nový objekt třídy členů bude nastaven v klonovaném objektu.
Přečtěte si více: Hluboké klonování pomocí in-memory serializace
Java Copy Konstruktory
Kopírovat konstruktory jsou speciální konstruktory ve třídě, která přebírá argument pro jeho vlastní typ třídy. Když tedy předáte instanci třídy ke kopírování konstruktoru, Konstruktor vrátí novou instanci třídy s hodnotami zkopírovanými z instance argumentu. To vám pomůže klonovat objekt s Cloneable rozhraní.
podívejme se na to v příkladu:
public class PointOne {private Integer x;private Integer y;public PointOne(PointOne point){this.x = point.x;this.y = point.y;}}
tato metoda vypadá jednoduše a je až do dědičnosti. Když definujete třídu rozšířením nad třídu, je třeba definovat podobný Konstruktor tam také. V podřízené třídě musíte zkopírovat atributy specifické pro dítě a předat argument konstruktoru super třídy. Uvidíme jak?
takže jsme v pořádku? Č. Problém s dědičností spočívá v tom, že přesné chování je identifikováno pouze za běhu. Takže v našem případě, pokud nějaká třída prošla instancí PointTwo
v konstruktoru PointOne
.
V tomto případě, budete mít instance PointOne
v návratu, kde si prošel instance PointTwo
jako argument. Podívejme se na to v kódu:
dalším způsobem, jak vytvořit Konstruktor kopírování, je mít statické tovární metody. Vezmou typ třídy v argumentu a vytvoří novou instanci pomocí jiného konstruktoru třídy. Pak se tyto tovární metody bude kopírovat všechny data stav k nové instanci třídy právě vytvořili v předchozím kroku, a vrátit této aktualizované stupně.
Java deep copy se serializací
serializace je další snadný způsob hlubokého klonování. V této metodě, jste jen serializaci objektu, který má být klonován a de-serializaci. Je zřejmé, že objekt, který je třeba klonovat, by měl implementovat rozhraní Serializable
.
než půjdu dál, měl bych upozornit, že tato technika se nemá používat lehce.
- Za prvé, serializace je nesmírně drahá. Mohlo by to být snadno stokrát dražší než metoda
clone()
. - za druhé, ne všechny objekty jsou
Serializable
. - za třetí, vytvoření třídy
Serializable
je složité a ne všechny třídy se mohou spolehnout na to, aby to bylo správné.
Přečtěte si více: příručka k implementaci serializace v Javě
Java clone – SerializationUtils
V Apache commons, SerializationUtils
třída má také utility funkce pro hluboké klonování. Pokud máte pocit, zájem sledovat jejich oficiální dokumenty.
<dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-lang3</artifactId> <version>3.7</version></dependency>
SomeObject cloned = org.apache.commons.lang.SerializationUtils.clone(someObject);
Java klon osvědčených postupů
- Když nevíte, zda můžete volat
clone()
metody konkrétní třídy, jak si nejste jisti, zda je implementováno v této třídě, můžete zkontrolovat s kontrolou, pokud je třída instance „Cloneable
“ rozhraní jak je uvedeno níže.if(obj1 instanceof Cloneable){ obj2 = obj1.clone();}//Dont do this. Cloneable dont have any methodsobj2 = (Cloneable)obj1.clone();
- na klonovaném objektu není volán Konstruktor. Jako výsledek, je vaší odpovědností, ujistit se, že všichni členové byli správně nastaveni. Také, pokud sledujete počet objektů v systému počítáním vyvolání konstruktérů, máte nové další místo pro zvýšení čítače.
doufám, že tento příspěvek byl opakovací pro vás a pomůže vám získat více informací o Java 8 klon metoda a je to správné použití. Pomůže také při odpovídání na otázky týkající se klonů Java.
šťastné učení !!