Deep Copy или Shallow Copy в Java - Как да изберем?

Deep_shallow_copy

Deep копие и плитко копие

Преглед: В тази статия ние ще обсъдим процеса на копиране на обекти в Java. Целта на копиране може да се различават в зависимост от изискването за прилагане. Но има главно два вида достъпно копиране, дълбоки и плитки копие. Методът на копиране варира в тези два подхода.

Въвеждане:
Действието на копиране на атрибутите на един обект в друг от същия тип данни се нарича обект копие. В Java, имаме следните подходи за копиране един обект в друг

  • Плитък Copy: Тук, ако областта, която трябва да бъде копиран е примитивен тип, След това стойността се копира друг Ако полето, което трябва да бъде копиран е адрес в паметта (или самия обект) след това на адреса се копира. Така ако адресът се променя от един обект, промяната се отразява навсякъде.
  • Deep Copy: Тук данните се копират и в двете ситуации. Този подход е по-скъпо и по-бавно.
  • Lazy Copy: Това е комбинация от горните два подхода. Първоначално подходът на плитко копие се използва и след това проверява дали данните се споделя от много обекти и програмата трябва да се промени един обект, се използва подхода на дълбоко копие.

Така че ние можем да изберете вида на копиране на базата на следните две условия

  • Използвайте плитки копиране, когато не се изисква капсулиране.
  • Използвайте дълбоко копиране, когато се изисква капсулиране.

Плитък Copy:

В плитки копие, нов обект е създаден, която съдържа точно копие на стойностите в оригиналния обект. Плитък копие следва подхода на битово-мъдър копие. В плитки копие, ако полето е адрес на паметта, след това на адреса се копира. Така ако адресът се променя от един обект, промяната се отразява навсякъде.

Shallow copy

Плитък копие

Figure 1: На схемата описва плитко копие

В тази цифра, обекта – mainObj1 има поле с име като Field1 на един примитивен тип каже инт, и обект от тип String Когато правим плитко копие на mainObj1, mainObj2 е създаден с Field2 от тип INT който съдържа копирани стойността на Field1 но String обект в mainObj2 – все още сочи към самия objStr. Тъй Field1 е примитивен тип данни, стойността на това се копира в Field2. Но тъй като objStr е обект, mainObj2 сочи към същия адрес на objStr. Така че всички промени, направени objStr чрез mainObj1 се отразяват в mainObj2.

изпълнение:

[код]

Listing 1: Клас SubjectVO.java описва стойност обект за теми

package com.home.objectCopy;

публичен клас SubjectVO {

частен име String;

/**

* @return името

*/

публичен String getName() {

return име;

}

/**

* @param име

* името, за да настроите

*/

публичен анулира setName(име String) {

this.име = име;

}

публичен SubjectVO(име String) {

this.име = име;

}

}

[/код]

Listing 2: Клас PupilVO.java описващ стойност обект за ученически

[код]

package com.home.objectCopy;

публичен клас PupilVO сечива Cloneable {

// Съдържащите се обект

частен SubjectVO субекта;

частен име String;

/**

* @return the субекта

*/

публичен SubjectVO getSubj() {

return субекта;

}

/**

* @param субекта

* the субекта за да зададете

*/

публичен анулира setSubj(SubjectVO субекта) {

this.субекта = субекта;

}

/**

* @return името

*/

публичен String getName() {

return име;

}

/**

* @param име

* името, за да настроите

*/

публичен анулира setName(име String) {

this.име = име;

}

публичен PupilVO(име String, String суб) {

this.име = име;

this.субекта = нов SubjectVO(под);

}

публичен клонинг Object() {

// плитко копие

опитвам {

return супер.клонинг();

} улов (CloneNotSupportedException д) {

return нула;

}

}

}

[/код]

Listing3: Клас ShallowCopyTest.java описващ процеса копие

[код]
package com.home.objectCopy;

публичен клас ShallowCopyTest {

публичен статичен анулира основен(Низ[] опцията) {

// Original Object

PupilVO родословни = нов PupilVO(“Johnathan”, “алгебра”);

Система.навън.println(“Original Object: ” + stud.getName() + ” – ”

+ stud.getSubj().getName());

// Clone Object

PupilVO clonedStud = (PupilVO) stud.clone();

Система.навън.println(“Клонирано Object: ” + clonedStud.getName() + ” – ”

+ clonedStud.getSubj().getName());

stud.setName(“Daniel”);

stud.getSubj().setName(“Физика”);

Система.навън.println(“Оригиналния обект, след това се актуализира: ”

+ stud.getName() + ” – ” + stud.getSubj().getName());

Система.навън.println(“Клонирано Object след обновяване на оригиналния обект: ”

+ clonedStud.getName() + ” – ”

+ clonedStud.getSubj().getName());

}

}

[/код]

продукция: Изходът от тази програма е като при

Original Object: Johnathan – алгебра

Клонирано Object: Johnathan – алгебра

Оригиналния обект, след това се актуализира: Daniel – Физика

Клонирано Object след обновяване на оригиналния обект: Johnathan – Физика

Тук виждаме, че стойността на името на полето бива променена след операция на копие, но стойността на обект предмет остава същата, тъй като е насочена към същия адрес памет. Следователно предмет на Джонатан става "Физика’ където както трябва да бъде "Алгебра’ като обект за SubjectVO в клонирания обект остава непроменена.

Deep Copy:

В дълбок копие, не само във всички сфери на даден обект се копират, всички динамично разпределени адреса на паметта, който е посочен от този обект също се копира.

Deep Cpoy

Deep Copy

Figure 2: Диаграмата описва дълбок процес копие

В тази цифра, на обект mainObj1 има полета Field1 примитивен тип данни казват, инт, и обект от тип String Когато правим дълбоко копие на mainObj1, mainObj2 е създаден с Field2, съдържаща копираните стойността на Field1 и objStr2 е създаден, който съдържа копирани стойността на objStr1 Така че всички промени, направени objStr1 в mainObj1 няма да се отрази в mainObj2.

изпълнение:

Listing4: Клас описващ дълбоко копие

[Code]

package com.home.DeepCopy;

публичен клас PupilVO сечива Cloneable {

// Съдържащите се обект

частен SubjectVO субекта;

частен име String;

/**

* @return the субекта

*/

публичен SubjectVO getSubj() {

return субекта;

}

/**

* @param субекта

* the субекта за да зададете

*/

публичен анулира setSubj(SubjectVO субекта) {

this.субекта = субекта;

}

/**

* @return името

*/

публичен String getName() {

return име;

}

/**

* @param име

* името, за да настроите

*/

публичен анулира setName(име String) {

this.име = име;

}

публичен PupilVO(име String, String суб) {

this.име = име;

this.субекта = нов SubjectVO(под);

}

публичен клонинг Object() {

// дълбоко копие

PupilVO ученик = нов PupilVO(име, subj.getName());

return ученик;

}

}

[/код]

Единствената разлика между този подход и по-рано подход е, че методът на клон в PupilVO връща новосъздадено PupilVO обект. Това гарантира, че всеки път, когато започна механизъм копие в, SubjectVO на обект също получава променено. Deep копие има алтернативен подход – сериализация. В сериализация, целия обект графиката е писано в постоянен магазин и чете обратно, когато е необходимо. Така че всеки път, когато четем обекта от персистираща магазина, оригиналния обект е посочена.

Употреба на плитко копие и дълбоко копие:

Не е трудно и бързо правило определено за избор между плитко копие и дълбоко копие, но обикновено ние трябва да имаме предвид, че ако един обект има само примитивни области, тогава очевидно, че трябва да отиде за плитко копие, но ако обектът има препратки към други обекти, След това въз основа на изискването, плитко копие или дълбоко копие трябва да се направи. Ако препратките не са актуализирани след това няма смисъл да се започне дълбока копие.

Обяснете мързелив копие:

Мързелив копие може да се дефинира като комбинация от двете плитки копие и дълбоко копие. Механизмът следва един прост подход – при първоначалното състояние, се използва подход плитко копие. А брояч се използва също така, за да следите за това как много обекти споделят данни. Когато програмата иска да променя оригиналния обект, тя проверява дали обектът е споделена или не. Ако обектът се споделя, След това се започва механизъм дълбоко копие.

Summary:

В плитки копие, само полета с примитивен тип данни се копират, а позоваванията на предмети, които не са копирани. Deep копие включва копие от примитивен тип данни, както и Objet препратки. Не е трудно и бързо правило за това кога да се направи плитки копие и кога да се направи дълбоко копие. Lazy копие е комбинация от двете от тези подходи.

Tagged on:
============================================= ============================================== Buy best TechAlpine Books on Amazon
============================================== ---------------------------------------------------------------- electrician ct chestnutelectric
error

Enjoy this blog? Please spread the word :)

Follow by Email
LinkedIn
LinkedIn
Share