Rozważ poniższy kod:
DummyBean dum = new DummyBean();
dum.setDummy("foo");
System.out.println(dum.getDummy()); // prints 'foo'
DummyBean dumtwo = dum;
System.out.println(dumtwo.getDummy()); // prints 'foo'
dum.setDummy("bar");
System.out.println(dumtwo.getDummy()); // prints 'bar' but it should print 'foo'
Tak, chcę skopiować dum
do dumtwo
i zmiana dum
bez wpływania na dumtwo
. Ale powyższy kod tego nie robi. Kiedy coś dum
zmieniam, zachodzi dumtwo
również ta sama zmiana .
Kiedy mówię dumtwo = dum
, Java kopiuje tylko odniesienie . Czy jest więc jakiś sposób na stworzenie nowej kopii dum
i przypisanie jej dumtwo
?
Podstawowy: Kopiowanie obiektów w Javie.
Załóżmy
obj1
, że obiekt- , który zawiera dwa obiekty, zawieraObj1 i zawieraObj2 .płytkie kopiowanie:
płytkie kopiowanie tworzy nowy
instance
z tej samej klasy i kopiuje wszystkie pola do nowej instancji i zwraca je. Klasa obiektowa zapewniaclone
metodę i obsługuje płytkie kopiowanie.Głębokie kopiowanie:
Głęboka kopia występuje, gdy obiekt jest kopiowany wraz z obiektami, do których się odnosi . Poniższe zdjęcie pokazuje
obj1
po wykonaniu na nim głębokiej kopii. Nie tylkoobj1
został skopiowany , ale również obiekty w nim zawarte zostały skopiowane. Możemy użyćJava Object Serialization
do wykonania głębokiej kopii. Niestety, takie podejście ma również pewne problemy ( szczegółowe przykłady ).Możliwe problemy:
clone
trudno jest poprawnie wdrożyć.Lepiej jest używać Defensywnego kopiowania , konstruktorów kopiowania (jako odpowiedź @egaga) lub statycznych metod fabrycznych .
clone()
metodę publiczną , ale nie znasz typu obiektu w czasie kompilacji, masz problem. Java ma interfejs o nazwieCloneable
. W praktyce powinniśmy wdrożyć ten interfejs, jeśli chcemy stworzyć obiektCloneable
.Object.clone
jest chroniony , dlatego musimy go zastąpić publiczną metodą, aby była dostępna.clone()
metoda wszystkich zmiennych obiektów składowych również wykonuje głębokie kopiowanie, jest to zbyt ryzykowne z założenia. Musisz kontrolować kod we wszystkich klasach.Na przykład org.apache.commons.lang.SerializationUtils będzie miał metodę głębokiego klonowania przy użyciu serializacji ( źródło ). Jeśli musimy sklonować Bean, istnieje kilka metod narzędziowych w org.apache.commons.beanutils ( Source ).
cloneBean
sklonuje komponent bean na podstawie dostępnych modułów pobierających i ustawiających właściwości, nawet jeśli sama klasa bean nie implementuje funkcji Cloneable.copyProperties
skopiuje wartości właściwości z komponentu bean źródłowego do komponentu bean docelowego dla wszystkich przypadków, w których nazwy właściwości są takie same.źródło
W pakiecie
import org.apache.commons.lang.SerializationUtils;
jest metoda:Przykład:
źródło
Serializable
Po prostu wykonaj następujące czynności:
i gdziekolwiek chcesz zdobyć inny obiekt, po prostu wykonaj klonowanie. na przykład:
źródło
Dlaczego nie ma odpowiedzi na użycie interfejsu API Reflection?
To jest naprawdę proste.
EDYCJA: Dołącz obiekt potomny poprzez rekurencję
źródło
Class A { B child; } Class B{ A parent; }
class car { car car = new car(); }
Korzystam z biblioteki Google JSON do serializacji, a następnie tworzę nową instancję serializowanego obiektu. Robi głębokie kopiowanie z kilkoma ograniczeniami:
nie może być żadnych rekurencyjnych odniesień
nie kopiuje tablic różnych typów
tablice i listy powinny być wpisane, w przeciwnym razie nie znajdzie klasy do utworzenia
może być konieczne enkapsulowanie łańcuchów w klasie, którą sam deklarujesz
Korzystam również z tej klasy do zapisywania preferencji użytkownika, okien i innych elementów, które należy ponownie załadować w czasie wykonywania. Jest bardzo łatwy w użyciu i skuteczny.
źródło
Tak, właśnie odwołujesz się do obiektu. Możesz sklonować obiekt, jeśli implementuje
Cloneable
.Sprawdź ten artykuł wiki na temat kopiowania obiektów.
Zobacz tutaj: Kopiowanie obiektów
źródło
Dodaj
Cloneable
kod poniżej i do swojej klasyUżyj tego
clonedObject = (YourClass) yourClassObject.clone();
źródło
Tak. Musisz głęboko skopiować swój obiekt.
źródło
To też działa. Zakładając model
Najpierw dodaj
compile 'com.google.code.gson:gson:2.8.1'
do swojej aplikacji> gradle & sync. NastępnieMożesz wykluczyć użycie pola za pomocą
transient
słowa kluczowego po modyfikatorze dostępu.Uwaga: to zła praktyka. Również nie polecam używać
Cloneable
lubJavaSerialization
Jest powolny i uszkodzony. Napisz konstruktor kopiowania dla najlepszej wydajności ref .Coś jak
Statystyki testowe iteracji 90000:
Linia
UserAccount clone = gson.fromJson(gson.toJson(aO), UserAccount.class);
zajmuje 808msLinia
UserAccount clone = new UserAccount(aO);
zajmuje mniej niż 1 msWniosek: użyj gson, jeśli twój szef jest szalony i wolisz szybkość. Jeśli wolisz jakość, użyj drugiego konstruktora kopii.
Możesz także użyć wtyczki generatora kodu konstruktora w Android Studio.
źródło
Oto przyzwoite wyjaśnienie,
clone()
czy w końcu będziesz go potrzebować ...Tutaj: klon (metoda Java)
źródło
Użyj narzędzia do głębokiego klonowania:
Spowoduje to głębokie skopiowanie dowolnego obiektu Java, sprawdź go na https://github.com/kostaskougios/cloning
źródło
Głębokie klonowanie jest odpowiedzią, która wymaga implementacji
Cloneable
interfejsu i zastąpieniaclone()
metody.Nazwiesz to tak
DummyBean dumtwo = dum.clone();
źródło
dummy
, aString
jest niezmienny, nie trzeba go kopiowaćAby to zrobić, musisz w jakiś sposób sklonować obiekt. Chociaż Java ma mechanizm klonowania, nie używaj go, jeśli nie musisz. Utwórz metodę kopiowania, która wykonuje kopiowanie, a następnie wykonaj następujące czynności:
Oto kilka porad dotyczących różnych technik tworzenia kopii.
źródło
Oprócz jawnego kopiowania, innym podejściem jest uczynienie obiektu niezmiennym (brak
set
lub inne metody mutatora). W ten sposób pytanie nigdy się nie pojawia. Niezmienność staje się trudniejsza w przypadku większych obiektów, ale z drugiej strony jest to, że popycha cię w kierunku podziału na spójne małe obiekty i kompozyty.źródło
Alternatywa dla konstruktorskiej metody kopiowania egaga . Prawdopodobnie masz już POJO, więc po prostu dodaj inną metodę,
copy()
która zwraca kopię zainicjowanego obiektu.Jeśli masz już
DummyBean
i chcesz kopię:Ale oba działają dobrze, to ostatecznie zależy od ciebie ...
źródło
źródło
Możesz głęboko kopiować automatycznie za pomocą XStream, z http://x-stream.github.io/ :
Dodaj go do swojego projektu (jeśli używasz maven)
Następnie
Dzięki temu masz kopię bez potrzeby implementowania interfejsu klonowania.
źródło
java.beans.XMLEncoder
na standardowy interfejs API języka Java, który również serializuje do formatu XML (choć nie jest to dokładnie do celów głębokiego kopiowania).i w twoim kodzie:
źródło
Przekaż obiekt, który chcesz skopiować, i uzyskaj żądany obiekt:
Teraz przeanalizuj
objDest
żądany obiekt.Happy Coding!
źródło
Możesz spróbować zaimplementować
Cloneable
i użyć tejclone()
metody; Jeśli jednak zastosować metodę klonowania ty powinien - według standardowych - nadpisywanie ZAWSZEObject
„spublic Object clone()
metody.źródło
Jeśli możesz dodać adnotację do pliku źródłowego, można użyć procesora adnotacji lub generatora kodu takiego jak ten .
Zostanie
DummyBeanBuilders
wygenerowana klasa , która ma statyczną metodędummyBeanUpdater
tworzenia płytkich kopii, w taki sam sposób, jak robiłbyś to ręcznie.źródło
Użyj
gson
do powielania obiektu.Przyjmijmy, mam obiektu
person
.Takźródło