klon jest dokładną kopią oryginału. W języku java oznacza to możliwość utworzenia obiektu o podobnym stanie jak obiekt oryginalny. Ta funkcjonalność zapewnia metoda java clone()
.
w tym poście omówimy większość ważnych aspektów 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 to jest klon Javy?
więc klonowanie polega na tworzeniu kopii oryginalnego obiektu. Jego słownikowe znaczenie to : „zrób identyczną kopię”.
domyślnie klonowanie Javy jest 'kopiowaniem pola po polu’, tzn. ponieważ klasa obiektu nie ma pojęcia o strukturze klasy, na której zostanie wywołana metoda clone ().
tak więc, JVM gdy zostanie wywołane do klonowania, wykonaj następujące czynności:
- jeśli klasa ma tylko prymitywne elementy typu danych, zostanie utworzona całkowicie nowa kopia obiektu i zostanie zwrócone odniesienie do nowej kopii obiektu.
- jeśli klasa zawiera elementy dowolnego typu klasy, to kopiowane są tylko odwołania do tych elementów, a zatem odwołania do elementów zarówno w oryginalnym obiekcie, jak i w sklonowanym obiekcie odnoszą się do tego samego obiektu.
oprócz powyższego domyślnego zachowania, zawsze możesz nadpisać to zachowanie i określić własne. Odbywa się to przy użyciu metody clone()
. Zobaczmy, jak to się robi.
Java Cloneable interface i metoda clone ()
każdy język, który obsługuje klonowanie obiektów, ma swoje własne reguły, podobnie jak java. W Javie, jeśli klasa musi obsługiwać klonowanie, musi wykonać następujące czynności:
- musisz zaimplementować interfejs
Cloneable
. - musisz nadpisać
clone()
metodę z klasy obiektu.
Czytaj więcej: Cloneable interface is broken in java
dokumenty Javy oclone()
metody są podane poniżej (sformatowane i wyodrębnione).
- pierwsza instrukcja gwarantuje, że sklonowany obiekt będzie miał osobne przypisanie adresów pamięci.
- druga Instrukcja sugeruje, że oryginalne i sklonowane obiekty powinny mieć ten sam typ klasy, ale nie jest to obowiązkowe.
- trzecia Instrukcja sugeruje, że oryginalne i sklonowane obiekty powinny być równe przy użyciu metody equals (), ale nie jest to obowiązkowe.
przyjrzyjmy się klonowi Javy z przykładem. Nasza pierwsza klasa toEmployee
klasa z 3 atrybutami – id
name
Idepartment
.
Department
klasa ma dwa atrybuty – id
Iname
.
więc, jeśli musimy sklonować klasę Employee, to musimy zrobić coś takiego.
świetnie, udało nam się sklonować obiekt Employee
. Pamiętaj jednak, że mamy dwa odniesienia do tego samego obiektu i teraz oba zmienią stan obiektu w różnych częściach aplikacji. Chcesz zobaczyć jak? Zobaczmy.
UPS, sklonowane zmiany obiektów są widoczne również w oryginale. W ten sposób sklonowane obiekty mogą spowodować spustoszenie w systemie, jeśli jest to dozwolone. Każdy może przyjść i sklonować obiekty aplikacji i robić, co mu się podoba. Czy możemy temu zapobiec??
odpowiedź brzmi Tak, możemy. Możemy temu zapobiec, tworząc Java deep copy i używając konstruktorów kopiujących. Dowiemy się o nich później w tym poście. Najpierw zobaczmy, co to jest głębokie klonowanie i płytkie klonowanie w Javie.
Java Shallow Copy
Shallow clone jest „domyślną implementacją” w Javie. W metodzie overridden clone
, jeśli nie klonujesz wszystkich typów obiektów (nie prymitywów), wykonujesz płytką kopię.
wszystkie powyższe przykłady są tylko płytką kopią, ponieważ nie sklonowaliśmy obiektuDepartment
w metodzieEmployee
klasyclone
. Teraz przejdę do następnej sekcji, gdzie zobaczymy Głębokie klonowanie.
Java Deep Copy
Deep clone jest pożądanym zachowaniem w większości przypadków. W głębokiej kopii tworzymy klon, który jest niezależny od oryginalnego obiektu i wprowadzanie zmian w sklonowanym obiekcie nie powinno mieć wpływu na oryginalny obiekt.
zobaczmy, jak głęboka kopia jest tworzona w Javie.
zmodyfikowałemEmployee
klasyclone()
I dodałem metodęclone
w klasieDepartment
.
teraz testowanie naszego kodu klonowania daje pożądany wynik i Nazwa działu nie zostanie zmodyfikowana.
tutaj zmiana stanu sklonowanego obiektu nie ma wpływu na oryginalny obiekt.
tak głębokie klonowanie wymaga spełnienia następujących zasad –
- nie ma potrzeby oddzielnego kopiowania prymitywów.
- wszystkie klasy członkowskie klasy oryginalnej powinny wspierać klonowanie, a w metodzie clone klasy oryginalnej w kontekście powinny wywoływać
super.clone()
na wszystkich klasach członkowskich. - jeśli któraś Klasa Członkowska nie obsługuje klonowania, to w metodzie clone należy utworzyć nową instancję tej klasy członkowskiej i skopiować wszystkie jej atrybuty jeden po drugim do nowego obiektu klasy członkowskiej. Ten nowy obiekt klasy member zostanie ustawiony w cloned object.
Czytaj więcej: Głębokie klonowanie przy użyciu serializacji w pamięci
Java Copy Constructors
Copy constructors są specjalnymi konstruktorami w klasie, która przyjmuje argument dla własnego typu klasy. Tak więc, gdy przekażesz instancję klasy do konstruktora kopiującego, konstruktor zwróci nową instancję klasy z wartościami skopiowanymi z instancji argumentu. Pomaga w klonowaniu obiektu z Klonowalnym interfejsem.
zobaczmy to w przykładzie:
public class PointOne {private Integer x;private Integer y;public PointOne(PointOne point){this.x = point.x;this.y = point.y;}}
ta metoda wygląda prosto i jest aż do dziedziczenia. Kiedy definiujesz klasę poprzez rozszerzenie powyżej klasy, musisz tam również zdefiniować podobny konstruktor. W klasie podrzędnej musisz skopiować atrybuty podrzędne i przekazać argument do konstruktora klasy nadrzędnej. Zobaczmy jak?
więc, wszystko w porządku? Nie. Problem z dziedziczeniem polega na tym, że dokładne zachowanie jest identyfikowane tylko w czasie wykonywania. Tak więc, w naszym przypadku, jeśli jakaś Klasa przeszła instancję PointTwo
w konstruktorze PointOne
.
w tym przypadku otrzymasz instancjęPointOne
w zamian, gdy przekazałeś instancjęPointTwo
jako argument. Zobaczmy to w kodzie:
innym sposobem tworzenia konstruktora kopii jest posiadanie statycznych metod fabrycznych. Biorą one Typ klasy w argumencie i tworzą nową instancję używając innego konstruktora klasy. Następnie te metody fabryczne skopiują wszystkie dane stanu do nowej instancji klasy utworzonej w poprzednim kroku i zwrócą tę zaktualizowaną instancję.
Java deep copy z serializacją
serializacja to kolejny łatwy sposób głębokiego klonowania. W tej metodzie po prostu serializujesz obiekt do klonowania i de-serializujesz go. Oczywiście obiekt, który ma zostać sklonowany powinien zaimplementować interfejsSerializable
.
zanim przejdę dalej, powinienem ostrzec, że tej techniki nie należy lekceważyć.
- po pierwsze serializacja jest bardzo droga. Z łatwością może być sto razy droższa niż metoda
clone()
. - Po drugie, nie wszystkie obiekty są
Serializable
. - Po Trzecie, Tworzenie klasy
Serializable
jest trudne i nie na wszystkich klasach można polegać, aby to zrobić dobrze.
Czytaj więcej: Przewodnik po implementacji serializacji w Javie
klonowanie Javy – SerializationUtils
w Apache commons, SerializationUtils
klasa ma również funkcję użytkową dla deep klonowanie. Jeśli czujesz się zainteresowany śledzić ich oficjalne 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);
najlepsze praktyki klonowania Javy
- gdy nie wiesz, czy możesz wywołać metodę
clone()
danej klasy, ponieważ nie masz pewności, czy jest ona zaimplementowana w tej klasie, możesz sprawdzić, czy klasa jest instancją interfejsu „Cloneable
” jak poniżej.if(obj1 instanceof Cloneable){ obj2 = obj1.clone();}//Dont do this. Cloneable dont have any methodsobj2 = (Cloneable)obj1.clone();
- na klonowanym obiekcie nie jest wywoływany żaden konstruktor. W rezultacie Twoim obowiązkiem jest upewnienie się, że wszyscy członkowie zostali odpowiednio ustawieni. Ponadto, jeśli śledzisz liczbę obiektów w systemie, licząc wywołania konstruktorów, masz nowe dodatkowe miejsce do zwiększania licznika.
Mam nadzieję, że ten post był dla Ciebie odświeżeniem i pomoże ci uzyskać więcej informacji na temat metody klonowania Java 8 i jej prawidłowego użycia. Pomoże również w odpowiadaniu na pytania dotyczące rozmów kwalifikacyjnych z klonem Javy.
udanej nauki !!