Java Academy · Oppitunti

Mukautettu serialisointi: writeObject ja readObject

Ohita writeObject- ja readObject-metodit salausta, pakkausta tai mukautettua kenttien käsittelyä varten.

Oppitunti 3/413 vaihetta

Mukautettu serialisointi: writeObject ja readObject on ilmainen Java Academy-oppitunti CoddyKitissä. Tämä on oppitunti 3/4. Voit lukea koko oppitunnin alta ilmaiseksi ja harjoitella sen jälkeen käytännössä selaimessa sisäänrakennetulla koodieditorilla ja ympäri vuorokauden käytettävissä olevan tekoälytuutorin avulla. Oppitunti kuuluu Java Academy-oppimispolkuun, ja edistymisesi synkronoituu verkon ja CoddyKit-sovelluksen välillä. Java Academy-kurssilla on yhteensä 4 oppituntia.

Kun oletusserialisointi ei riitä

Oletusserialisointi tallentaa kaikki ei-transient-kentät sellaisinaan. Joskus tarvitaan salausta, pakkausta tai erilaista esitysmuotoa. Tällöin käyttöön tulevat writeObject- ja readObject-koukut.

writeObject-metodin määrittäminen

Lisätkää metodi private void writeObject(ObjectOutputStream oos). Java kutsuu sitä oletusmekanismin sijaan. Hallitsette tällöin tarkasti, mitä kirjoitetaan.

private void writeObject(ObjectOutputStream oos) throws IOException {
    oos.defaultWriteObject(); // write non-transient fields normally
    oos.writeUTF(encrypt(this.secret)); // write encrypted secret
}

readObject-metodin määrittäminen

Lisätkää metodi private void readObject(ObjectInputStream ois). Java kutsuu sitä deserialisoinnin aikana. Lukekaa tiedot täsmälleen samassa järjestyksessä kuin kirjoititte ne.

private void readObject(ObjectInputStream ois)
        throws IOException, ClassNotFoundException {
    ois.defaultReadObject(); // restore non-transient fields
    this.secret = decrypt(ois.readUTF()); // decrypt and restore
}

Järjestyksellä on merkitystä

Kaikki, mitä kirjoitatte metodissa writeObject, on luettava takaisin samassa järjestyksessä metodissa readObject. Eroava järjestys aiheuttaa poikkeuksen StreamCorruptedException.

private void writeObject(ObjectOutputStream oos) throws IOException {
    oos.writeInt(version);
    oos.writeUTF(data);
}
private void readObject(ObjectInputStream ois)
        throws IOException, ClassNotFoundException {
    this.version = ois.readInt();  // same order
    this.data    = ois.readUTF();
}

Tietojen pakkaaminen serialisoinnin aikana

Käärikää virta metodissa writeObject luokan GZIPOutputStream sisään suurten kenttien pakkaamiseksi ja käyttäkää sitten luokkaa GZIPInputStream metodissa readObject tietojen purkamiseen.

private void writeObject(ObjectOutputStream oos) throws IOException {
    oos.defaultWriteObject();
    ByteArrayOutputStream bos = new ByteArrayOutputStream();
    try (GZIPOutputStream gz = new GZIPOutputStream(bos)) {
        gz.write(largePayload.getBytes());
    }
    oos.writeObject(bos.toByteArray());
}

readResolve-koukku

readResolve()-metodia kutsutaan deserialisoinnin jälkeen. Palauttakaa korvaava olio — tämä on hyödyllistä singletonien ja enumeraatioiden yhteydessä, jotta deserialisoinnin jälkeen on olemassa vain yksi instanssi.

public class AppConfig implements Serializable {
    private static final AppConfig INSTANCE = new AppConfig();
    private AppConfig() {}
    public static AppConfig getInstance() { return INSTANCE; }
    private Object readResolve() { return INSTANCE; } // return singleton
}

writeReplace-koukku

writeReplace()-metodia kutsutaan ennen serialisointia. Palauttakaa sen sijaan serialisoitava toinen olio — tämä on hyödyllistä välityspalvelinmalleissa ja serialisoinnin korvaavissa olioissa.

private Object writeReplace() {
    return new UserProxy(this.id); // serialize a lightweight proxy
}

Kenttien validointi readObject-metodissa

Voitte lisätä readObject-metodiin validointilogiikkaa, joka hylkää virheelliset tai peukaloidut tiedot osana kerroksittaista puolustusstrategiaa.

private void readObject(ObjectInputStream ois)
        throws IOException, ClassNotFoundException {
    ois.defaultReadObject();
    if (age < 0 || age > 150) {
        throw new InvalidObjectException("Invalid age: " + age);
    }
}

Versiomuutosten käsittely

Käyttäkää vers||||kenttää metodissa writeObject, jotta readObject pystyy käsittelemään sekä vanhoja että uusia muotoja hallitusti siirtymien aikana.

private static final int SERIAL_VERSION = 2;
private void writeObject(ObjectOutputStream oos) throws IOException {
    oos.defaultWriteObject();
    oos.writeInt(SERIAL_VERSION);
    if (SERIAL_VERSION >= 2) oos.writeUTF(email); // new field
}
private void readObject(ObjectInputStream ois)
        throws IOException, ClassNotFoundException {
    ois.defaultReadObject();
    int v = ois.readInt();
    if (v >= 2) this.email = ois.readUTF();
}

Serialisoinnin välityspalvelinmalli

Vankka toimintatapa on kirjoittaa yksityinen staattinen sisäluokka, joka tallentaa vähimmäistilan, käyttää writeReplace-metodia välityspalvelimen kirjoittamiseen ja sen readResolve-metodia alkuperäisen olion muodostamiseen.

Suorituskykynäkökohdat

Mukautettu serialisointi lisää metodikutsujen aiheuttamaa kuormaa, mutta voi pienentää siirrettävän aineiston kokoa huomattavasti. Mitatkaa suorituskyky ennen optimointia ja käyttäkää Externalizablea, kun tarvitsette mahdollisimman täyden hallinnan.

Pikatarkistus

Mitä writeObject- ja readObject-metodien suoritusjärjestyksestä on pidettävä paikkansa?

Kertaus

Ohittakaa writeObject- ja readObject-metodit salausta, pakkausta tai mukautettuja muotoja varten. Käyttäkää readResolve-metodia singletonien yhteydessä. Lukekaa tiedot aina samassa järjestyksessä kuin kirjoitatte ne.

Aloita maksutta

Opi Java tekoälytuutorin avulla — ilmaiseksi

Kirjoita ja suorita oikeaa koodia selaimessa, saa välitöntä apua tekoälytuutorilta ympäri vuorokauden ja jatka siitä, mihin jäit, verkossa tai sovelluksessa.

Kurssit
104
Oppitunnit
374

Usein kysytyt kysymykset

Onko oppitunti ”Mukautettu serialisointi: writeObject ja readObject” ilmainen?

Kyllä – oppitunnin ”Mukautettu serialisointi: writeObject ja readObject” koko tekstin voi lukea täällä verkossa ilmaiseksi. Jos haluat harjoitella interaktiivisesti sisäänrakennetulla koodieditorilla ja ympäri vuorokauden käytettävissä olevan tekoälytuutorin avulla sekä avata koko Java Academy-kurssin, päivitä CoddyKit PROhon. Java Academy-kurssilla on yhteensä 4 oppituntia.

Mitä opin oppitunnilla ”Mukautettu serialisointi: writeObject ja readObject”?

Ohita writeObject- ja readObject-metodit salausta, pakkausta tai mukautettua kenttien käsittelyä varten. Harjoittelet Java Academy-aihetta koodilla, jonka suoritat suoraan selaimessa. Ympäri vuorokauden käytettävissä oleva tekoälytuutori vastaa kysymyksiisi oppitunnin aikana.

Tarvitsenko kokemusta aloittaakseni Java Academy-opiskelun?

Aiempi kokemus ei ole tarpeen. CoddyKitin Java Academy-oppimispolku sopii vasta-alkajista edistyneisiin, joten voit aloittaa tästä tai alusta ja edetä omaan tahtiisi. Tämä on oppitunti 3/4.

Kuinka kauan ”Mukautettu serialisointi: writeObject ja readObject”-oppitunnin suorittaminen kestää?

Useimmat CoddyKitin oppitunnit kestävät noin 5–10 minuuttia. Jokainen oppitunti on lyhyt ja interaktiivinen, joten edistyt tasaisesti ja voit jatkaa siitä, mihin jäit – sekä verkossa että sovelluksessa.

Voinko kirjoittaa ja suorittaa koodia tällä Java Academy-oppitunnilla?

Kyllä. Jokainen Java Academy-oppitunti sisältää sisäänrakennetun koodieditorin, joten voit kirjoittaa ja suorittaa oikeaa koodia suoraan selaimessa ja saada välitöntä palautetta tekoälyltä – paikallista asennusta ei tarvita.

Kaikki tämän kurssin oppitunnit

  1. Javan serialisoinnin perusteet
  2. transient-kentät ja serialVersionUID
  3. Mukautettu serialisointi: writeObject ja readObject
  4. Nykyaikaiset vaihtoehdot: JSON ja Protocol Buffers
← Takaisin: Java Academy