Vodič za eksternalizirano sučelje u Javi

1. Uvod

U ovom vodiču, brzo ćemo pogledati Java java.io.Externalizable sučelje. Glavni cilj ovog sučelja je olakšati prilagođenu serializaciju i deserializaciju.

Prije nego što nastavimo, provjerite članak o serializaciji u Javi. Sljedeće je poglavlje o tome kako serializirati Java objekt s ovim sučeljem.

Nakon toga razgovarat ćemo o ključnim razlikama u odnosu na java.io.Serializable sučelje.

2. The Eksternalizirati Sučelje

Eksternalizirati proteže se od java.io.Serializable sučelje markera. Bilo koja klasa koja implementira Eksternalizirati sučelje bi trebalo nadjačati writeExternal (), readExternal () metode. Na taj način možemo promijeniti zadano ponašanje JVM-a za serializaciju.

2.1. Serijalizacija

Pogledajmo ovaj jednostavan primjer:

javna klasa Country implementira Externalizable {private static final long serialVersionUID = 1L; privatni naziv niza; privatni int kod; // getters, setters @Override public void writeExternal (ObjectOutput out) baca IOException {out.writeUTF (name); out.writeInt (kod); } @Override public void readExternal (ObjectInput in) baca IOException, ClassNotFoundException {this.name = in.readUTF (); this.code = in.readInt (); }}

Ovdje smo definirali razred Zemlja koja provodi Eksternalizirati sučelje i implementira dvije gore spomenute metode.

U writeExternal () metodu dodajemo svojstva objekta u ObjectOutput potok. Ovo ima standardne metode poput writeUTF () za Niz i writeInt () za vrijednosti int.

Sljedeći, za deserializaciju predmeta čitamo iz ObjectInput potok koristiti readUTF (), readInt () metode za čitanje svojstava istim redoslijedom kojim su napisana.

Dobra je praksa dodati serialVersionUID ručno. Ako toga nema, JVM će ga automatski dodati.

Automatski generirani broj ovisi o prevoditelju. To znači da to može prouzročiti malo vjerojatno InvalidClassException.

Isprobajmo ponašanje koje smo gore primijenili:

@Test public void whenSerializing_thenUseExternalizable () baca IOException, ClassNotFoundException {Country c = new Country (); c.setCode (374); c.setName ("Armenija"); FileOutputStream fileOutputStream = novi FileOutputStream (OUTPUT_FILE); ObjectOutputStream objectOutputStream = novi ObjectOutputStream (fileOutputStream); c.writeExternal (objectOutputStream); objectOutputStream.flush (); objectOutputStream.close (); fileOutputStream.close (); FileInputStream fileInputStream = novi FileInputStream (OUTPUT_FILE); ObjectInputStream objectInputStream = novi ObjectInputStream (fileInputStream); Zemlja c2 = nova zemlja (); c2.readExternal (objectInputStream); objectInputStream.close (); fileInputStream.close (); assertTrue (c2.getCode () == c.getCode ()); assertTrue (c2.getName (). jednako (c.getName ())); }

U ovom primjeru prvo stvaramo Zemlja objekt i zapisivanje u datoteku. Zatim izvršavamo deserializaciju objekta iz datoteke i provjeravamo jesu li vrijednosti ispravne.

Izlaz ispisanog c2 objekt:

Država {name = 'Armenija', code = 374}

To pokazuje da smo uspješno deserijalizirali objekt.

2.2. Nasljeđivanje

Kada klasa nasljeđuje od Serijalizirati sučelje, JVM automatski prikuplja i sva polja iz podklasa i čini ih serializirajućima.

Imajte na umu da to možemo primijeniti na Eksternalizirati također. Samo trebamo implementirati metode čitanja / pisanja za svaku podklasu hijerarhije nasljeđivanja.

Pogledajmo Regija klasa ispod koje se proteže naša Zemlja razred iz prethodnog odjeljka:

javna klasa Regija se proširuje Zemlja implementira Externalizable {private static final long serialVersionUID = 1L; privatna gudačka klima; privatno dvostruko stanovništvo; // getters, setters @Override public void writeExternal (ObjectOutput out) baca IOException {super.writeExternal (out); out.writeUTF (klima); } @Override public void readExternal (ObjectInput in) baca IOException, ClassNotFoundException {super.readExternal (in); this.climate = in.readUTF (); }}

Ovdje smo dodali dva dodatna svojstva i serializirali prvo.

Imajte na umu da zvali smo i mi super.writeExternal (out), super.readExternal (in) unutar metoda serializatora za spremanje / vraćanje i polja roditeljske klase.

Pokrenimo jedinični test sa sljedećim podacima:

Regija r = nova Regija (); r.setCode (374); r.setName ("Armenija"); r.setClimate ("Mediteran"); r.setPopulacija (120.000);

Evo deserializiranog objekta:

Regija {country = "Country {name =" Armenia ', code = 374}' klima = "Mediteran", stanovništvo = null}

Primijeti da budući da nismo serializirali populacija polje u Regija klase, vrijednost tog svojstva je null.

3. Eksternalizirati nasuprot Serijalizirati

Prođimo kroz ključne razlike između dva sučelja:

  • Odgovornost za serializaciju

Ključna razlika ovdje je u tome kako postupamo s postupkom serializacije. Kad razred provodi java.io.Serializable sučelje, JVM preuzima punu odgovornost za serializaciju instance klase. U slučaju Eksternalizirati, programer je taj koji bi se trebao pobrinuti za čitav postupak serializacije, a također i za deserializaciju.

  • Slučaj upotrebe

Ako trebamo serializirati cijeli objekt, Serijalizirati sučelje je bolje. S druge strane, za prilagođenu serializaciju možemo kontrolirati postupak pomoću Eksternalizirati.

  • Izvođenje

The java.io.Serializable sučelje koristi refleksiju i metapodatke što uzrokuje relativno sporo izvođenje. Za usporedbu, Eksternalizirati sučelje vam daje potpunu kontrolu nad postupkom serializacije.

  • Red za čitanje

Dok se koristi Eksternalizirati, obavezno je pročitati sva stanja polja u točnom redoslijedu kako su napisana. U suprotnom, dobit ćemo iznimku.

Na primjer, ako promijenimo redoslijed čitanja kodirati i Ime svojstva u Zemlja razred, a java.io.EOFException bit će bačen.

U međuvremenu, Serijalizirati sučelje nema taj zahtjev.

  • Prilagođena serializacija

Prilagođenu serializaciju možemo postići pomoću Serijalizirati sučelje označavanjem polja sa prolazan ključna riječ. JVM neće serializirati određeno polje, ali će dodati polje za pohranu datoteka sa zadanom vrijednošću. Zato je dobra praksa Eksternalizirati u slučaju prilagođene serializacije.

4. Zaključak

U ovom kratkom vodiču za Eksternalizirati sučelja, razgovarali smo o ključnim značajkama, prednostima i demonstrirali primjere jednostavne uporabe. Također smo napravili usporedbu s Serijalizirati sučelje.

Kao i obično, puni izvorni kod udžbenika dostupan je na GitHubu.