Java-klooni-deep ja shallow copy – copy-rakentajat

klooni on tarkka kopio alkuperäisestä. Jaavalla se tarkoittaa olennaisesti kykyä luoda olio, jonka tila on samankaltainen kuin alkuperäisen olion. Java clone() – menetelmä tarjoaa tämän toiminnallisuuden.

tässä viestissä tutustutaan useimpiin Java-kloonin tärkeisiin puoliin.

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

mikä on Java-klooni?

kloonauksessa on siis kyse alkuperäisen objektin kopion luomisesta. Sen sanakirjan merkitys on : ”tee identtinen kopio”.

oletuksena java-kloonaus on ”field by field copy” eli Objektiluokalla ei ole käsitystä luokan rakenteesta, johon kloonausmenetelmään() vedotaan.

joten, JVM kun pyydetään kloonaamaan, tee seuraavat asiat:

  1. Jos luokassa on vain alkeellisia tietotyypin jäseniä, luodaan objektista kokonaan uusi kopio ja palautetaan viittaus uuteen objektikopioon.
  2. Jos luokka sisältää minkä tahansa luokkatyypin jäseniä, niin vain objektiviittaukset näihin jäseniin kopioidaan ja siten sekä alkuperäisen objektin että kloonatun objektin jäsenviittaukset viittaavat samaan objektiin.

edellä olevan oletuskäyttäytymisen lisäksi voit aina ohittaa tämän käyttäytymisen ja määrittää omasi. Tämä tehdään käyttämällä ohitusta clone() – menetelmää. Katsotaan, miten se tehdään.

Java Cloneable interface and clone() method

jokaisella objektien kloonausta tukevalla kielellä on omat sääntönsä, kuten myös Javalla. Javassa, jos luokka tarvitsee tukea kloonausta sen on tehtävä seuraavat asiat:

  1. sinun on toteutettava Cloneable käyttöliittymä.
  2. clone() metodi Olioluokasta.

Lue lisää: Kloneable interface is broken in java

Java docs about clone() method are given below (formated and extract).

  1. ensimmäinen lauseke takaa, että kloonatulle kohteelle annetaan erillinen muistiosoite.
  2. toisen lausuman mukaan alkuperäisillä ja kloonatuilla esineillä pitäisi olla sama luokkatyyppi, mutta se ei ole pakollista.
  3. kolmas lauseke esittää, että alkuperäisten ja kloonattujen kappaleiden olisi pitänyt olla yhtä suuria käyttäen equals () – menetelmää, mutta se ei ole pakollinen.

ymmärretään Java-klooni esimerkin avulla. Ensimmäinen luokkamme on Employee Luokka, jossa on 3 attribuuttia – idname ja department.

Department luokalla on kaksi ominaisuutta – id ja name.

joten, jos meidän täytyy kloonata Työntekijäluokka, niin meidän täytyy tehdä jotain tällaista.

Suuri, onnistuimme kloonaamaan Employee objektin. Mutta muista, että meillä on kaksi viittausta samaan objektiin ja nyt molemmat muuttavat objektin tilaa sovelluksen eri osissa. Haluatko nähdä miten? Katsotaanpa.

Hups, kloonatut esinemuutokset näkyvät myös alkuperäisessä. Näin kloonatut esineet voivat tehdä tuhoa järjestelmässä, jos niiden sallitaan tehdä niin. Kuka tahansa voi tulla kloonaamaan sovelluskohteesi ja tehdä mitä haluaa. Voimmeko estää tämän??

vastaus on kyllä, voimme. Voimme estää tämän luomalla Java deep copy ja käyttää copy constructors. Opimme niistä myöhemmin tässä viestissä. Katsotaan ensin, mitä on syvä Kloonaus ja matala Kloonaus Jaavalla.

Java Shallow Copy

Shallow clone on ”oletustoteutus” Javassa. Ohitetussa clone method, jos ei kloonata kaikkia oliotyyppejä (ei primitiivejä), tehdään pinnallinen kopio.

kaikki edellä mainitut esimerkit ovat vain pinnallisia kopioita, koska emme ole kloonanneet Department objektia Employee luokan clone menetelmällä. Siirryn seuraavaan osioon, jossa näemme syvän kloonauksen.

Java Deep Copy

Deep clone on useimmissa tapauksissa toivottu käyttäytyminen. Syvässä kopiossa luodaan klooni, joka on riippumaton alkuperäisestä objektista ja muutosten tekeminen kloonattuun objektiin ei saisi vaikuttaa alkuperäiseen objektiin.

katsotaan, miten syvä kopio on luotu Javassa.

muutin Employee classes clone() method and added following clone method in Department class.

nyt kloonauskoodimme testaus antaa halutun tuloksen, eikä osaston nimeä muuteta.

tässä kloonatun kappaleen tilan muuttuminen ei vaikuta alkuperäiseen kappaleeseen.

niin syvä Kloonaus vaatii tyydytystä seuraavista säännöistä –

  • primitiivejä ei tarvitse erikseen kopioida.
  • kaikkien alkuperäisen luokan jäsenluokkien tulisi tukea kloonausta ja alkuperäisen luokan kloonimenetelmässä kontekstissa tulisi kutsua super.clone() kaikille jäsenluokille.
  • Jos jokin jäsenluokka ei tue kloonausta kloonausmenetelmällä, täytyy luoda uusi ilmentymä kyseisestä jäsenluokasta ja kopioida kaikki sen attribuutit yksitellen uuteen jäsenluokan objektiin. Tämä uusi jäsenluokan objekti asetetaan kloonattuun objektiin.

Lue lisää: Syväkloonaus käyttäen muistisarjaa

Java-kopioiden rakentajat

kopioiden rakentajat ovat erityisiä konstruktioita luokassa, joka ottaa argumentin omalle luokkatyypilleen. Niin, kun ohitat esimerkiksi luokan kopioida constructor, sitten constructor palauttaa uuden ilmentymän luokan arvot kopioitu argumentti instance. Se auttaa kloonaamaan objektin Kloonattavalla käyttöliittymällä.

katsotaan tämä esimerkissä:

public class PointOne {private Integer x;private Integer y;public PointOne(PointOne point){this.x = point.x;this.y = point.y;}}

tämä menetelmä näyttää yksinkertaiselta ja se on kunnes tulee periytyminen. Kun määrittelet luokan laajentamalla luokan yläpuolelle, sinun täytyy määritellä samanlainen rakentaja sielläkin. Lapsiluokassa täytyy kopioida lapsikohtaisia ominaisuuksia ja siirtää argumentti superluokan rakentajalle. Katsotaan miten?

joten, olemmeko nyt kunnossa? Ei. Periytymisen ongelma on se, että tarkka käyttäytyminen tunnistetaan vain ajettaessa. Eli meidän tapauksessamme, jos joku Luokka läpäisi instanssin PointTwo konstruktorin PointOne.

tässä tapauksessa saat instanssin PointOne vastineeksi, jossa ohitit instanssin PointTwo argumenttina. Katsotaan tämä koodilla:

toinen tapa luoda kopiokonstruktori on staattiset tehdasmenetelmät. He ottavat luokan tyypin argumentissa ja luovat uuden instanssin käyttämällä toista luokan konstruktoria. Sitten nämä tehdasmenetelmät kopioi kaikki valtion tiedot uuteen luokkaan esimerkiksi juuri luotu edellisessä vaiheessa, ja palauttaa tämän päivitetyn esiintymän.

Java deep copy with serialization

Serialization on toinen helppo tapa syväkloonata. Tässä menetelmässä kloonattava esine vain sarjoidaan ja se de-serialisoidaan. On selvää, että kloonattavan kohteen tulisi toteuttaa Serializable liitäntä.

ennen kuin menen pidemmälle, minun on varoitettava, että tätä tekniikkaa ei saa käyttää kevyesti.

  1. ensinnäkin sarjalisointi on valtavan kallista. Se voisi helposti tulla sata kertaa kalliimmaksi kuin clone() menetelmä.
  2. toiseksi kaikki oliot eivät ole Serializable.
  3. kolmas, luokan Serializable tekeminen on hankalaa, eikä kaikkiin luokkiin voi luottaa, että se onnistuisi.

Lue lisää: opas sarjallistamisen toteuttamiseen Javassa

Java – klooni-SerializationUtils

Apache Commonsissa, SerializationUtils luokassa on myös hyödyllisyysfunktio syväkloonausta. Jos olet kiinnostunut, seuraa heidän virallisia dokumentteja.

<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 clone best practices

  1. kun et tiedä, voiko clone() tietyn luokan menetelmää kutsua, koska et ole varma, onko se toteutettu kyseisessä luokassa, voit tarkistaa, jos luokka on instanssi ”Cloneable” liittymä kuten alla.
    if(obj1 instanceof Cloneable){ obj2 = obj1.clone();}//Dont do this. Cloneable dont have any methodsobj2 = (Cloneable)obj1.clone();
  2. yhdellekään konstruktorille ei kutsuta kloonattavaa esinettä. Näin ollen on teidän vastuullanne varmistaa, että kaikki jäsenet on asetettu asianmukaisesti. Myös, jos olet pitää kirjaa määrä esineitä järjestelmässä laskemalla invocation rakentajien, saat uuden lisäpaikan lisätä laskuri.

toivon, että tämä viesti on ollut kertaus sinulle ja auttaa sinua saamaan lisätietoja Java 8-kloonimenetelmästä ja sen oikeasta käytöstä. Se auttaa myös vastaamalla Java klooni haastattelu kysymyksiin.

onnellista oppimista !!

oliko tästä viestistä apua?

kerro, piditkö viestistä. Se on ainoa tapa parantaa.
Kyllä
Ei

Vastaa

Sähköpostiosoitettasi ei julkaista. Pakolliset kentät on merkitty *