CodeGym /Blog Jawa /Acak /Serialisasi lan deserialisasi ing Jawa
John Squirrels
tingkat
San Francisco

Serialisasi lan deserialisasi ing Jawa

Diterbitake ing grup
Hi! Ing wulangan dina iki, kita bakal ngomong babagan serialisasi lan deserialisasi ing basa Jawa. Kita bakal miwiti karo conto prasaja. Bayangake sampeyan minangka pangembang game komputer. Yen sampeyan tansaya munggah ing 90s lan elinga nyenengake game ing jaman sing, sampeyan mbokmenawa ngerti sing padha kurang soko kita njupuk kanggo diwenehake dina - kemampuan kanggo nyimpen lan mbukak game :) Yen ora, mbayangno!Serialisasi lan deserialisasi ing Jawa - 1Aku wedi yen game tanpa kabisan iki dina iki bakal pinasthi! Oalah, apa tegese 'nyimpen' lan 'muat' game? Inggih, kita ngerti makna saben dinten: kita pengin nerusake game saka papan sing kita tinggalake. Kanggo nindakake iki, kita nggawe 'titik mriksa' tartamtu sing digunakake mengko kanggo mbukak game. Nanging apa tegese kanggo programmer tinimbang tukang game sembrono? Jawaban iki prasaja: kita nyimpen negara program kita. Ayo dadi ngomong sampeyan lagi main Spanyol ing game strategi. Game sampeyan duwe negara: wilayah endi sing diduweni saben wong, pira sumber daya sing diduweni saben wong, apa aliansi sing ana lan karo sapa, sing perang, lan liya-liyane. Informasi iki, negara program kita, kudu piye wae disimpen kanggo mulihake data lan nerusake game. Kaya mengkono, Serialisasi ing Jawa yaiku proses nyimpen status obyek minangka urutan bita. Deserialisasi ing Jawa yaiku proses mulihake obyek saka bita kasebut. Sembarang obyek Jawa bisa diowahi dadi urutan byte. Napa kita butuh iki? Kita wis bola-bali ujar manawa program ora ana dhewe. Paling asring, padha sesambungan karo siji liyane, ijol-ijolan data, etc. Format byte trep lan efisien kanggo iki. Contone, kita bisa ngowahi obyek saka SavedGame kitakelas menyang urutan bait, nransfer bait iki liwat jaringan kanggo komputer liyane, lan banjur ing komputer liyane Ngonversi bita iki bali menyang obyek Jawa! Iku muni angel, huh? Iku misale jek bakal angel kanggo nggawe iki kabeh kelakon: / Untunge, iku ora! :) Ing Jawa, antarmuka Serializable tanggung jawab kanggo proses serialization. Antarmuka iki gampang banget: Sampeyan ora kudu ngetrapake cara siji kanggo nggunakake! Deleng carane prasaja kelas kita kanggo nyimpen game:

import java.io.Serializable;
import java.util.Arrays;

public class SavedGame implements Serializable {

   private static final long serialVersionUID = 1L;

   private String[] territoryInfo;
   private String[] resourceInfo;
   private String[] diplomacyInfo;

   public SavedGame(String[] territoryInfo, String[] resourceInfo, String[] diplomacyInfo){
       this.territoryInfo = territoryInfo;
       this.resourceInfo = resourceInfo;
       this.diplomacyInfo = diplomacyInfo;
   }

   public String[] getTerritoryInfo() {
       return territoryInfo;
   }

   public void setTerritoryInfo(String[] territoryInfo) {
       this.territoryInfo = territoryInfo;
   }

   public String[] getResourceInfo() {
       return resourceInfo;
   }

   public void setResourceInfo(String[] resourceInfo) {
       this.resourceInfo = resourceInfo;
   }

   public String[] getDiplomacyInfo() {
       return diplomacyInfo;
   }

   public void setDiplomacyInfo(String[] diplomacyInfo) {
       this.diplomacyInfo = diplomacyInfo;
   }

   @Override
   public String toString() {
       return "SavedGame{" +
               "territoryInfo=" + Arrays.toString(territoryInfo) +
               ", resourceInfo=" + Arrays.toString(resourceInfo) +
               ", diplomacyInfo=" + Arrays.toString(diplomacyInfo) +
               '}';
   }
}
Telung array tanggung jawab kanggo informasi babagan wilayah, sumber daya, lan diplomasi, lan antarmuka Serializable ngandhani mesin Jawa: ' kabeh apik yen obyek saka kelas iki bisa serialized '. Antarmuka tanpa antarmuka siji katon aneh : / Kenapa perlu? Jawaban kanggo pitakonan kasebut ing ndhuwur: mung perlu kanggo nyedhiyakake informasi sing dibutuhake kanggo mesin Java. Ing pawulangan kepungkur, kita sebutno sedhela antarmuka panandha. Iki minangka antarmuka informasi khusus sing mung menehi tandha kelas kita kanthi informasi tambahan sing bakal migunani kanggo mesin Java ing mangsa ngarep. Dheweke ora duwe cara sing kudu sampeyan lakoni. Punika Serializable - siji antarmuka kuwi. Punika titik penting liyane: Apa kita kuduvariabel serialVersionUID final statis pribadi sing kita ditetepake ing kelas? Lapangan iki ngemot pengenal versi unik saka kelas serialized. Saben kelas sing ngleksanakake antarmuka Serializable duwe pengenal versi. Ditemtokake adhedhasar isi kelas - kolom lan urutan deklarasi, lan metode lan urutan deklarasi. Lan yen kita ngganti jinis lapangan lan / utawa nomer lapangan ing kelas kita, pengenal versi diganti langsung. SerialVersionUID uga ditulis nalika kelas kasebut serialized . Nalika kita nyoba deserialize, IE mulihake obyek saka urutan byte, Nilai serialVersionUID dibandhingake karo nilai serialVersionUID .saka kelas ing program kita. Yen nilai ora cocog, banjur java.io.InvalidClassException bakal dibuwang. Kita bakal weruh conto ing ngisor iki. Kanggo ngindhari kahanan kasebut, kita mung nyetel pengenal versi kanggo kelas kita kanthi manual. Ing kasus kita, mung bakal padha karo 1 (sampeyan bisa nggunakake nomer liyane sing disenengi). Ya, wektune nyoba nggawe serialisasi obyek SavedGame lan ndeleng apa sing kedadeyan!

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;

public class Main {

   public static void main(String[] args) throws IOException {

       // Create our object
       String[] territoryInfo = {"Spain has 6 provinces", "Russia has 10 provinces", "France has 8 provinces"};
       String[] resourceInfo = {"Spain has 100 gold", "Russia has 80 gold", "France has 90 gold"};
       String[] diplomacyInfo = {"France is at war with Russia, Spain has taken a neutral position"};

       SavedGame savedGame = new SavedGame(territoryInfo, resourceInfo, diplomacyInfo);

       // Create 2 streams to serialize the object and save it to a file
       FileOutputStream outputStream = new FileOutputStream("C:\\Users\\Username\\Desktop\\save.ser");
       ObjectOutputStream objectOutputStream = new ObjectOutputStream(outputStream);

       // Save the game to a file
       objectOutputStream.writeObject(savedGame);

       // Close the stream and release resources
       objectOutputStream.close();
   }
}
Kaya sing sampeyan ngerteni, kita nggawe 2 aliran: FileOutputStream lan ObjectOutputStream . Sing pisanan ngerti carane nulis data menyang file, lan sing kapindho ngowahi obyek dadi bita. Sampeyan wis ndeleng konstruksi nested sing padha, contone, new BufferedReader(new InputStreamReader(...)) , ing pelajaran sadurunge, supaya sampeyan ora wedi :) Kanthi nggawe rantai loro aliran iki, kita nindakake tugas loro: kita Ngonversi SavedGame obyek menyang urutan bita lan nyimpen menyang file nggunakake writeObject () cara. Lan, kanthi cara, kita malah ora ndeleng apa sing kita entuk! Wektu kanggo ndeleng file kasebut! * Cathetan: ora perlu nggawe file sadurunge. Yen file kanthi jeneng sing ditemtokake ora ana, banjur bakal digawe kanthi otomatis* Lan ing ngisor iki isine: ¬н sr SavedGame [ diplomacyInfot [Ljava/lang/String;[ resourceInfoq ~ [ territoryInfoq ~ xpur [Ljava.lang. String;¬ТVзй{G xp t pPr¤СЂР°РЅС†РёСЏРІРсюет СЃ РРсссией, Русский РёС† Rusia етаuq ~ t "Rp. Рё 90 Р·РѕР » uq ~ t & Русский Русский 6 Русский №t &РЈ Франции 8 провинций Oh, oh :( Kayane program kita ora bisa digunakake : ( Bener, kerjane. Sampeyan elinga yen kita ngirim urutan bait, lan ora mung obyek utawa teks, menyang file? Nah, iki urutan bait iki. katon kaya :) Iki minangka game sing wis disimpen! Yen kita pengin mulihake obyek asli, yaiku miwiti lan nerusake game sing ditinggalake, mula kita butuh proses mbalikke: deserialization. Iki sing katon kanggo kita:

import java.io.*;

public class Main {

   public static void main(String[] args) throws IOException, ClassNotFoundException {

       FileInputStream fileInputStream = new FileInputStream("C:\\Users\\Username\\Desktop\\save.ser");
       ObjectInputStream objectInputStream = new ObjectInputStream(fileInputStream);

       SavedGame savedGame = (SavedGame) objectInputStream.readObject();

       System.out.println(savedGame);
   }
}
Lan iki asile! SavedGame{territoryInfo=[Spanyol duwé 6 provinsi, Rusia duwé 10 provinsi, Prancis duwé 8 provinsi], resourceInfo=[Spanyol duwé 100 emas, Rusia duwé 80 emas, Prancis duwé 90 emas], diplomasiInfo=[Prancis perang karo Rusia, Spanyol wis njupuk posisi netral]} Apik banget! Kita bisa pisanan nyimpen negara game kita menyang file, lan banjur mulihake saka file. Saiki ayo nyoba nindakake perkara sing padha, nanging kita bakal mbusak pengenal versi saka kelas SavedGame . Kita ora bakal nulis ulang loro kelas kita. Kode dheweke bakal padha. Kita mung bakal mbusak serialVersionUID final statis pribadi saka kelas SavedGame . Punika obyek kita sawise serialization: ¬н sr SavedGameі€MіuОm‰ [ diplomacyInfot [Ljava/lang/String;[ resourceInfoq ~ [ territoryInfoq ~ xpur [Ljava.lang.String;¬ТVзй{G xp t pФранциСЗСЗРА ЃСЃРёРµР№, RUSSARI ё 100 R °t Udhara 80 Udr uq ~ t & r6 ЂРѕРІРёРЅС†РёР№t %РЈ Р РѕѓСѓрё 10 bagean & рёр№t & Рјјјрђрёрђрђрђрђрceрірірёрёрception: Stream Classesc SerialversionUid = -19 6410440475012755 , serialversionuid kelas lokal = -6675950253085108747 Miturut cara, kita ora kejawab soko penting. Temenan, strings lan primitif gampang serialized: Jawa mesthi wis sawetara mekanisme dibangun ing iki. Nanging apa yen kelas serializable kita duwe lapangan sing ora primitif, nanging referensi kanggo obyek liyane? Contone, ayo nggawe kelas TerritoryInfo , ResourceInfo lan DiplomacyInfo sing kapisah kanggo nggarap kelas SavedGame kita .

public class TerritoryInfo {

   private String info;

   public TerritoryInfo(String info) {
       this.info = info;
   }

   public String getInfo() {
       return info;
   }

   public void setInfo(String info) {
       this.info = info;
   }

   @Override
   public String toString() {
       return "TerritoryInfo{" +
               "info='" + info + '\'' +
               '}';
   }
}

public class ResourceInfo {

   private String info;

   public ResourceInfo(String info) {
       this.info = info;
   }

   public String getInfo() {
       return info;
   }

   public void setInfo(String info) {
       this.info = info;
   }

   @Override
   public String toString() {
       return "ResourceInfo{" +
               "info='" + info + '\'' +
               '}';
   }
}

public class DiplomacyInfo {

   private String info;

   public DiplomacyInfo(String info) {
       this.info = info;
   }

   public String getInfo() {
       return info;
   }

   public void setInfo(String info) {
       this.info = info;
   }

   @Override
   public String toString() {
       return "DiplomacyInfo{" +
               "info='" + info + '\'' +
               '}';
   }
}
Lan saiki kita ngadhepi pitakonan: Apa kabeh kelas iki kudu Serializable yen kita pengin serialize kelas SavedGame kita?

import java.io.Serializable;
import java.util.Arrays;

public class SavedGame implements Serializable {

   private TerritoryInfo territoryInfo;
   private ResourceInfo resourceInfo;
   private DiplomacyInfo diplomacyInfo;

   public SavedGame(TerritoryInfo territoryInfo, ResourceInfo resourceInfo, DiplomacyInfo diplomacyInfo) {
       this.territoryInfo = territoryInfo;
       this.resourceInfo = resourceInfo;
       this.diplomacyInfo = diplomacyInfo;
   }

   public TerritoryInfo getTerritoryInfo() {
       return territoryInfo;
   }

   public void setTerritoryInfo(TerritoryInfo territoryInfo) {
       this.territoryInfo = territoryInfo;
   }

   public ResourceInfo getResourceInfo() {
       return resourceInfo;
   }

   public void setResourceInfo(ResourceInfo resourceInfo) {
       this.resourceInfo = resourceInfo;
   }

   public DiplomacyInfo getDiplomacyInfo() {
       return diplomacyInfo;
   }

   public void setDiplomacyInfo(DiplomacyInfo diplomacyInfo) {
       this.diplomacyInfo = diplomacyInfo;
   }

   @Override
   public String toString() {
       return "SavedGame{" +
               "territoryInfo=" + territoryInfo +
               ", resourceInfo=" + resourceInfo +
               ", diplomacyInfo=" + diplomacyInfo +
               '}';
   }
}
Oke, banjur! Ayo padha nyoba! Saiki, kita bakal ninggalake kabeh lan nyoba nggawe serialize obyek SavedGame :

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;

public class Main {

   public static void main(String[] args) throws IOException {

       // Create our object
       TerritoryInfo territoryInfo = new TerritoryInfo("Spain has 6 provinces, Russia has 10 provinces, France has 8 provinces");
       ResourceInfo resourceInfo = new ResourceInfo("Spain has 100 gold, Russia has 80 gold, France has 90 gold");
       DiplomacyInfo diplomacyInfo =  new DiplomacyInfo("France is at war with Russia, Spain has taken a neutral position");


       SavedGame savedGame = new SavedGame(territoryInfo, resourceInfo, diplomacyInfo);

       FileOutputStream fileOutputStream = new FileOutputStream("C:\\Users\\Username\\Desktop\\save.ser");
       ObjectOutputStream objectOutputStream = new ObjectOutputStream(fileOutputStream);

       objectOutputStream.writeObject(savedGame);

       objectOutputStream.close();
   }
}
Asil: Pangecualian ing utas "utama" java.io.NotSerializableException: DiplomacyInfo Ora bisa! Dadi, iki jawaban kanggo pitakonan kita. Nalika obyek serialized, kabeh obyek sing dirujuk dening variabel Kayata serialized. Lan yen obyek kasebut uga ngrujuk marang obyek liyane, mula uga ana serial. Lan ing lan ing salawas-lawase. Kabeh kelas ing chain iki kudu Serializable , yen ora, bakal mokal kanggo serialize lan pangecualian bakal di buwang. Miturut cara, iki bisa nggawe masalah ing dalan. Contone, apa sing kudu kita lakoni yen kita ora butuh bagean saka kelas sajrone serialisasi? Utawa apa yen kita entuk kelas TerritoryInfo 'liwat warisan' minangka bagéan saka perpustakaan? Lan umpamane yen iku 'lan, miturut, kita ora bisa ngganti. Iki tegese kita ora bisa nambah lapangan TerritoryInfo menyang kelas SavedGame , amarga kabeh kelas SavedGame bakal dadi unserializable! Iku masalah: / Serialisasi lan deserialisasi ing Jawa - 2Ing Jawa, masalah iki ditanggulangi kanthi tembung kunci transient . Yen sampeyan nambahake tembung kunci iki menyang lapangan kelas sampeyan, kolom kasebut ora bakal diseralisasi. Ayo dadi nyoba nggawe salah siji saka lapangan SavedGame kelas transient , banjur kita bakal serialize lan mulihake obyek siji.

import java.io.Serializable;

public class SavedGame implements Serializable {

   private transient TerritoryInfo territoryInfo;
   private ResourceInfo resourceInfo;
   private DiplomacyInfo diplomacyInfo;

   public SavedGame(TerritoryInfo territoryInfo, ResourceInfo resourceInfo, DiplomacyInfo diplomacyInfo) {
       this.territoryInfo = territoryInfo;
       this.resourceInfo = resourceInfo;
       this.diplomacyInfo = diplomacyInfo;
   }

   // ...getters, setters, toString()...
}



import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;

public class Main {

   public static void main(String[] args) throws IOException {

       // Create our object
       TerritoryInfo territoryInfo = new TerritoryInfo("Spain has 6 provinces, Russia has 10 provinces, France has 8 provinces");
       ResourceInfo resourceInfo = new ResourceInfo("Spain has 100 gold, Russia has 80 gold, France has 90 gold");
       DiplomacyInfo diplomacyInfo =  new DiplomacyInfo("France is at war with Russia, Spain has taken a neutral position");


       SavedGame savedGame = new SavedGame(territoryInfo, resourceInfo, diplomacyInfo);

       FileOutputStream fileOutputStream = new FileOutputStream("C:\\Users\\Username\\Desktop\\save.ser");
       ObjectOutputStream objectOutputStream = new ObjectOutputStream(fileOutputStream);

       objectOutputStream.writeObject(savedGame);

       objectOutputStream.close();
   }
}


import java.io.*;

public class Main {

   public static void main(String[] args) throws IOException, ClassNotFoundException {

       FileInputStream fileInputStream = new FileInputStream("C:\\Users\\Username\\Desktop\\save.ser");
       ObjectInputStream objectInputStream = new ObjectInputStream(fileInputStream);

       SavedGame savedGame = (SavedGame) objectInputStream.readObject();

       System.out.println(savedGame);

       objectInputStream.close();


   }
}
Lan iki asile: SavedGame{territoryInfo=null, resourceInfo=ResourceInfo{info='Spanyol duwe 100 emas, Rusia duwe 80 emas, Prancis duwe 90 emas'}, diplomacyInfo=DiplomacyInfo{info='Prancis perang karo Rusia, Spanyol wis njupuk posisi netral'}} Ngandika, kita entuk jawaban kanggo pitakonan apa nilai sing bakal ditugasake menyang lapangan transien . Diwenehi nilai standar. Kanggo obyek, iki null . Sampeyan bisa maca bab sing apik banget babagan topik iki ing buku 'Kepala-Kawitan Jawa', Digatekake :)
Komentar
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION