CodeGym /Blog Jawa /Acak /Apa bedane serialisasi lan deseralisasi ing Jawa?
John Squirrels
tingkat
San Francisco

Apa bedane serialisasi lan deseralisasi 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. Ayo dadi ngomong sampeyan wis nggawe game komputer. Yen sampeyan tuwuh ing taun 90-an lan ngelingi konsol game ing jaman kasebut, sampeyan bisa uga ngerti manawa dheweke ora duwe apa-apa sing kita lakoni saiki - kemampuan kanggo nyimpen lan mbukak game :) Yen ora, bayangake! Apa bedane serialisasi lan deseralisasi ing Jawa?  - 1 Aku wedi yen dina iki game tanpa kabisan iki bakal pinasthi! Apa tegese "nyimpen" lan "muat" game? Ya, kita ngerti makna biasa: kita pengin nerusake game kasebut saka papan sing kita tinggalake. Kanggo nindakake iki, kita nggawe jinis "titik mriksa", sing banjur digunakake kanggo mbukak game. Nanging apa tegese iki kanggo programmer tinimbang tukang game sembrono? Jawaban iki prasaja: kita'. Ayo dadi ngomong sampeyan lagi main minangka Spanyol ing Strategium. Game sampeyan duwe negara: sing duwe wilayah endi, sing duwe sumber daya, sing ana ing aliansi karo sapa, sing perang karo sapa, lan liya-liyane. Kita kudu piye wae nyimpen informasi iki, negara program kita, kanggo mulihake ing mangsa lan terus game. Kanggo iki persis apa serialization lan deserealization kanggo. Serialisasi yaiku proses nyimpen kahanan obyek ing urutan bita. Deserialisasiyaiku proses mulihake obyek saka bait kasebut. Sembarang obyek Jawa bisa diowahi dadi urutan byte. Yagene kita butuh kuwi? Kita wis ngandika luwih saka sapisan sing program ora ana ing dhewe. Paling asring, padha sesambungan karo program liyane, ijol-ijolan data, lan sapiturute. Lan urutan byte minangka format sing trep lan efisien. Contone, kita bisa ngowahi SavedGameobyek kita dadi urutan bita, ngirim bait kasebut liwat jaringan menyang komputer liyane, banjur ing komputer kapindho ngowahi bait kasebut bali menyang obyek Jawa! Muni angel, bener? Lan ngleksanakake proses iki katon kaya rasa lara: / Untunge, ora kaya ngono! :) Ing Jawa, ingSerializableantarmuka tanggung jawab kanggo proses serialization. Antarmuka iki gampang banget: sampeyan ora perlu ngleksanakake cara siji kanggo nggunakake! Mangkene carane kelas nyimpen game katon prasaja:

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

public class SavedGame implements Serializable {

   private static final long serialVersionUID = 1L;

   private String[] territoriesInfo;
   private String[] resourcesInfo;
   private String[] diplomacyInfo;

   public SavedGame(String[] territoriesInfo, String[] resourcesInfo, String[] diplomacyInfo){
       this.territoriesInfo = territoriesInfo;
       this.resourcesInfo = resourcesInfo;
       this.diplomacyInfo = diplomacyInfo;
   }

   public String[] getTerritoriesInfo() {
       return territoriesInfo;
   }

   public void setTerritoriesInfo(String[] territoriesInfo) {
       this.territoriesInfo = territoriesInfo;
   }

   public String[] getResourcesInfo() {
       return resourcesInfo;
   }

   public void setResourcesInfo(String[] resourcesInfo) {
       this.resourcesInfo = resourcesInfo;
   }

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

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

   @Override
   public String toString() {
       return "SavedGame{" +
               "territoriesInfo=" + Arrays.toString(territoriesInfo) +
               ", resourcesInfo=" + Arrays.toString(resourcesInfo) +
               ", diplomacyInfo=" + Arrays.toString(diplomacyInfo) +
               '}';
   }
}
Telung array tanggung jawab kanggo informasi babagan wilayah, sumber daya, lan diplomasi. Antarmuka Serializable ngandhani mesin virtual Jawa: " Kabeh iku OK - yen perlu, obyek saka kelas iki bisa serialized ". Antarmuka tanpa antarmuka siji katon aneh : / Kenapa perlu? Jawaban kanggo pitakonan iki bisa katon ing ndhuwur: mung serves kanggo nyedhiyani informasi perlu kanggo mesin virtual Jawa. Ing salah sawijining pawulangan sadurunge, kita sebutake 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.Serializableiku salah siji saka antarmuka. Titik penting liyane: Napa kita butuh private static final long serialVersionUIDvariabel sing ditetepake ing kelas? Kenapa perlu? Lapangan iki ngemot pengenal unik kanggo versi kelas serialized . Sembarang kelas sing ngleksanakake Serializableantarmuka duwe versionpengenal. Diwilang adhedhasar isi kelas: kolom, urutan sing diumumake, metode, lan liya-liyane. Yen kita ngganti jinis lapangan lan / utawa jumlah kolom ing kelas kita, pengenal versi langsung diganti . serialVersionUIDuga ditulis nalika kelas serialized. Nalika kita nyoba deserialize, yaiku, mulihake obyek saka sakumpulan bita, sing digandhengake serialVersionUIDdibandhingake karo nilaiserialVersionUIDkanggo kelas ing program kita. Yen nilai ora cocog, banjur java.io. InvalidClassException bakal dibuwang. Kita bakal weruh conto ing ngisor iki. Kanggo ngindhari iki, kita mung nyetel pengenal versi kanthi manual ing kelas kita. Ing kasus kita, mung bakal padha karo 1 (nanging sampeyan bisa ngganti nomer liyane sing disenengi). Inggih, iku wektu kanggo nyoba kanggo serialize SavedGameobyek kita lan ndeleng apa mengkono!

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[] resourcesInfo = {"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, resourcesInfo, 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 free resources
       objectOutputStream.close();
   }
}
Nalika sampeyan bisa ndeleng, kita digawe 2 stream: FileOutputStreamlan ObjectOutputStream. Sing pisanan bisa 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" saka rong aliran kasebut, kita nindakake tugas loro: kita ngowahi obyek kasebut SavedGamedadi set. saka bita lan simpen menyang file nggunakake writeObject()metode kasebut. Lan, kanthi cara, kita malah ora ndeleng apa sing kita entuk! Wektu kanggo ndeleng file kasebut! * Cathetan: sampeyan ora kudu nggawe file sadurunge. Yen file kanthi jeneng kasebut ora ana, file kasebut bakal digawe kanthi otomatis * Lan iki isine!

¬н sr SavedGame [ diplomacyInfot [Ljava/lang/String;[ resourcesInfoq ~ [ territoriesInfoq ~ xpur [Ljava.lang.String;­ТVзй{G xp t pФранция воюет СЃ Россией, Испания заняла позицию нейтралитетаuq ~ t "РЈ Испании 100 золотаt РЈ Р РѕСЃСЃРёРё 80 золотаt !РЈ Франции 90 золотаuq ~ t &РЈ Испании 6 провинцийt %РЈ Р РѕСЃСЃРёРё 10 провинцийt &РЈ Франции 8 провинций
Uh-oh :( Kayane program kita ora bisa digunakake :( Nyatane, bisa. Sampeyan kelingan yen kita ngirim set bita, ora mung obyek utawa teks, menyang file? Nah, iki sing set bita 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. Mangkene apa sing bakal katon ing kita . kasus:

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{territoriesInfo=["Spain has 6 provinces, Russia has 10 provinces, France has 8 provinces], resourcesInfo=[Spain has 100 gold, Russia has 80 gold, France has 90 gold], diplomacyInfo=[France is at war with Russia, Spain has taken a neutral position]}
Banget! Kita ngatur kanggo nyimpen negara game kanggo file, banjur mulihake saka file. Saiki ayo nyoba nindakake perkara sing padha, nanging tanpa pengenal versi kanggo SavedGamekelas kita. Kita ora bakal nulis ulang loro kelas kita. Kode bakal tetep padha, nanging kita bakal mbusak private static final long serialVersionUIDsaka SavedGamekelas. Punika obyek kita sawise serialization:

¬н sr SavedGameі€MіuОm‰ [ diplomacyInfot [Ljava/lang/String;[ resourcesInfoq ~ [ territoriesInfoq ~ xpur [Ljava.lang.String;­ТVзй{G xp t pФранция воюет СЃ Россией, Испания заняла позицию нейтралитетаuq ~ t "РЈ Испании 100 золотаt РЈ Р РѕСЃСЃРёРё 80 золотаt !РЈ Франции 90 золотаuq ~ t &РЈ Испании 6 провинцийt %РЈ Р РѕСЃСЃРёРё 10 провинцийt &РЈ Франции 8 провинций
Nanging deleng apa sing kedadeyan nalika kita nyoba deserialize:

InvalidClassException: local class incompatible: stream classdesc serialVersionUID = -196410440475012755, local class serialVersionUID = -6675950253085108747
Iki minangka pangecualian sing wis kasebut ing ndhuwur. Miturut cara, kita ora kejawab soko penting. Iku ndadekake pangertèn sing Strings lan primitif bisa gampang serialized: Jawa mbokmenawa wis sawetara jinis dibangun ing mekanisme kanggo nindakake iki. Nanging kepiye yen serializablekelas kita duwe lapangan sing dudu primitif, nanging referensi kanggo obyek liyane? Contone, ayo nggawe kapisah TerritoriesInfo, ResourcesInfolan DiplomacyInfokelas kanggo nggarap SavedGamekelas kita.

public class TerritoriesInfo {
  
   private String info;

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

   public String getInfo() {
       return info;
   }

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

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

public class ResourcesInfo {

   private String info;

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

   public String getInfo() {
       return info;
   }

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

   @Override
   public String toString() {
       return "ResourcesInfo{" +
               "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 ana pitakonan: apa kabeh kelas kasebut kudu dadi Serializableyen kita pengin nggawe seri SavedGamekelas sing diowahi?

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

public class SavedGame implements Serializable {

   private TerritoriesInfo territoriesInfo;
   private ResourcesInfo resourcesInfo;
   private DiplomacyInfo diplomacyInfo;

   public SavedGame(TerritoriesInfo territoriesInfo, ResourcesInfo resourcesInfo, DiplomacyInfo diplomacyInfo) {
       this.territoriesInfo = territoriesInfo;
       this.resourcesInfo = resourcesInfo;
       this.diplomacyInfo = diplomacyInfo;
   }

   public TerritoriesInfo getTerritoriesInfo() {
       return territoriesInfo;
   }

   public void setTerritoriesInfo(TerritoriesInfo territoriesInfo) {
       this.territoriesInfo = territoriesInfo;
   }

   public ResourcesInfo getResourcesInfo() {
       return resourcesInfo;
   }

   public void setResourcesInfo(ResourcesInfo resourcesInfo) {
       this.resourcesInfo = resourcesInfo;
   }

   public DiplomacyInfo getDiplomacyInfo() {
       return diplomacyInfo;
   }

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

   @Override
   public String toString() {
       return "SavedGame{" +
               "territoriesInfo=" + territoriesInfo +
               ", resourcesInfo=" + resourcesInfo +
               ", diplomacyInfo=" + diplomacyInfo +
               '}';
   }
}
Inggih, ayo dites! Ayo ninggalake kabeh kaya apa wae lan nyoba nggawe serial SavedGameobyek:

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(territoriesInfo, resourcesInfo, diplomacyInfo);

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

       objectOutputStream.writeObject(savedGame);

       objectOutputStream.close();
   }
}
asil:

Exception in thread "main" java.io.NotSerializableException: DiplomacyInfo
Ora bisa! Sejatine, iki jawaban kanggo pitakonan kita. Nalika obyek wis serialized, kabeh obyek sing dirujuk dening variabel conto sawijining serialized. Lan yen obyek kasebut uga ngrujuk marang obyek liyane, mula uga ana serial. Lan ing ad infinitum. Kabeh kelas ing chain iki kuduSerializable , yen ora, iku bakal mokal kanggo serialize lan pangecualian bakal di buwang. Miturut cara, iki bisa nggawe masalah ing dalan. Apa sing kudu kita tindakake yen, contone, kita ora perlu bagéan saka kelas nalika kita serialize? Utawa, contone, apa yen TerritoryInfokelas teka kita minangka bagéan saka sawetara perpustakaan pihak katelu. Lan umpamane luwih ora Serializable, lan kita ora bisa ngganti. Pranyata kita ora bisa nambah TerritoryInfolapangan kanggo kitaSavedGamekelas, amarga mengkono bakal nggawe kabeh SavedGamekelas non- serializable! Iku masalah: / Apa bedane serialisasi lan deseralisasi ing Jawa?  - 2Ing Jawa, masalah kaya iki ditanggulangi nggunakake transienttembung kunci. Yen sampeyan nambahake tembung kunci iki menyang lapangan kelas sampeyan, kolom kasebut ora bakal diseralisasi. Ayo nyoba nggawe salah sawijining SavedGamelapangan conto kelas dadi transient. Banjur kita bakal serialize lan mulihake siji obyek.

import java.io.Serializable;

public class SavedGame implements Serializable {

   private transient TerritoriesInfo territoriesInfo;
   private ResourcesInfo resourcesInfo;
   private DiplomacyInfo diplomacyInfo;

   public SavedGame(TerritoriesInfo territoriesInfo, ResourcesInfo resourcesInfo, DiplomacyInfo diplomacyInfo) {
       this.territoriesInfo = territoriesInfo;
       this.resourcesInfo = resourcesInfo;
       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(territoriesInfo, resourcesInfo, 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{territoriesInfo=null, resourcesInfo=ResourcesInfo{info='Spain has 100 gold, Russia has 80 gold, France has 90 gold'}, diplomacyInfo=DiplomacyInfo{info='France is at war with Russia, Spain has taken a neutral position'}}
Kajaba iku, kita entuk jawaban kanggo pitakonan babagan nilai apa sing bakal diwenehake menyang transientlapangan. Iku bakal diutus nilai gawan. Kanggo obyek, iki null. Sampeyan bisa maca artikel iki apik banget babagan serialization nalika sampeyan duwe sawetara menit kanggo nyisakke. Iku uga nyebataken Externalizableantarmuka, kang bakal kita pirembagan bab ing pawulangan sabanjuré. Kajaba iku, buku "Kepala-Kawitan Jawa" nduweni bab babagan topik iki. Ojo lali perhatian :)
Komentar
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION