JavaRush /Blog Jawa /Random-JV /Serialisasi lan Deserialisasi ing Jawa

Serialisasi lan Deserialisasi ing Jawa

Diterbitake ing grup
Hello! Wonten ing pawiyatan dinten punika badhe kaandharaken babagan serialisasi saha deseralisasi ing basa Jawi. Ayo dadi miwiti karo conto prasaja. Sebutake sampeyan sing nggawe game komputer. Yen tansaya munggah ing 90s lan elinga nyenengake game sing kaping, sampeyan mbokmenawa ngerti sing padha kurang soko ketok dina - nyimpen lan loading game :) Yen ora ... mbayangno! Aku wedi yen dina iki game tanpa pilihan kuwi bakal pinasthi gagal! Lan, bener, apa "nyimpen" lan "muat" game? Inggih, ing pangertèn biasanipun, kita ngerti apa iku: kita pengin nerusake game saka ngendi kita ninggalake pungkasan wektu. Kanggo nindakake iki, kita nggawe jenis "checkpoint", kang banjur digunakake kanggo mbukak game. Nanging apa tegese iki, ora ing pangertèn saben dina, nanging ing pangertèn "programmer"? Jawaban iki prasaja: kita nyimpen negara program kita. Ayo dadi ngomong sampeyan lagi main game strategi kanggo Spanyol. Game sampeyan duwe negara: sing duwe wilayah apa, sing duwe sumber daya, sing aliansi karo sapa, lan sapa wae sing perang, lan liya-liyane. Informasi iki, negara program kita, kudu disimpen piye wae supaya mengko mulihake data lan nerusake game. Iki persis apa mekanisme serialisasi lan deserialization digunakake . Serialisasi yaiku proses nyimpen kahanan obyek menyang urutan bita. Deserialisasi yaiku proses rekonstruksi obyek saka bita kasebut. Sembarang obyek Jawa diowahi dadi urutan bita. Kanggo apa? Kita wis ngandika luwih saka sapisan sing program ora ana ing dhewe. Paling asring padha sesambungan karo saben liyane, ijol-ijolan data, etc. Lan format bait trep lan efisien kanggo iki. Contone, kita bisa ngowahi obyek kelas SavedGame(game sing disimpen) dadi urutan bait, nransfer bait kasebut liwat jaringan menyang komputer liyane, lan ing komputer kapindho ngowahi bait kasebut dadi obyek Jawa! Iku angel krungu, ta? Ketoke, ngatur proses iki ora bakal gampang: / Untunge, ora! :) Ing Jawa, antarmuka Serializable tanggung jawab kanggo proses serialization . Antarmuka iki gampang banget: sampeyan ora perlu ngleksanakake cara siji kanggo nggunakake! Mangkene carane kelas save game bakal katon kaya:

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 set data tanggung jawab kanggo informasi babagan wilayah, ekonomi lan diplomasi, lan antarmuka Serializable ngandhani mesin Java: " kabeh iku ok, yen ana, obyek saka kelas iki bisa serialized ." Antarmuka sing ora duwe metode katon aneh: / Kenapa perlu? Jawaban kanggo pitakonan iki ndhuwur: mung kanggo nyedhiyani informasi perlu kanggo mesin Java. Ing salah sawijining ceramah sadurunge, kita sebutake sedhela antarmuka panandha. Iki minangka antarmuka informatif 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 ditindakake. Dadi, Serializable minangka salah sawijining antarmuka kasebut. Titik penting liyane: variabel private static final long serialVersionUIDsing ditetepake ing kelas. Kenapa perlu? Kolom iki ngemot pengenal versi unik saka kelas serial . Sembarang kelas sing ngleksanakake antarmuka Serializable duwe pengenal versi. Iki diitung adhedhasar isi kelas - kolom, urutan deklarasi, metode. Lan yen kita ngganti jinis lapangan lan / utawa nomer lapangan ing kelas kita, pengenal versi bakal langsung ngganti. serialVersionUID uga ditulis nalika kelas serialized. Nalika kita nyoba kanggo deserialize, sing, mulihake obyek saka pesawat saka bita, Nilai serialVersionUIDdibandhingake karo Nilai serialVersionUIDsaka kelas ing program kita. Yen nilai ora cocog, java.io.InvalidClassException bakal dibuwang. Kita bakal weruh conto ing ngisor iki. Kanggo ngindhari kahanan kaya mengkono, kita mung nyetel ID versi iki kanthi manual kanggo kelas kita. Ing kasus kita, mung bakal padha karo 1 (sampeyan bisa ngganti nomer liyane sing disenengi). Inggih, iku wektu kanggo nyoba serializing obyek kita SavedGamelan 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 position of neutrality"};

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

       //create 2 threads 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 game to file
       objectOutputStream.writeObject(savedGame);

       // close the stream and release resources
       objectOutputStream.close();
   }
}
Nalika sampeyan bisa ndeleng, kita wis nggawe 2 Utas - FileOutputStreamlan ObjectOutputStream. Sing pisanan bisa nulis data menyang file, lan sing kapindho bisa ngowahi obyek dadi bita. Sampeyan wis ndeleng konstruksi "nested" sing padha, umpamane, new BufferedReader(new InputStreamReader(...))ing kuliah sadurunge, mula sampeyan ora kudu wedi :) Kanthi nggawe "rantai" saka rong benang, kita nindakake tugas loro: kita ngowahi obyek kasebut SavedGamedadi set bita. lan simpen menyang file nggunakake metode writeObject(). Lan, kanthi cara, kita malah ora mriksa apa sing kita entuk! Wektu kanggo ndeleng file kasebut! * Cathetan: file ora perlu digawe luwih dhisik. Yen file kanthi jeneng kasebut ora ana, bakal digawe kanthi otomatis * Lan iki isine! ¬н sr SavedGame [ diplomacyInfot [Ljava/lang/String;[ resourcesInfoq ~ [ territoriesInfoq ~ xpur [Ljava.lang.String;ТVзй{G xp t pФранцвоюетSЃСЋРµС‚SЃСАР, РЃСА їР° UTS UQ ~ t "UJR00° таt Р J R Basa Inggris: 80 Русский t ! РЅС †РёР№t %РЈ Р РсСЃСЃРёРё 10 РїСЂРѕРІРёРЅС †РёР№t &РЈ ФранцРеРё 8 проввинций Oops :( Iku misale jek program kita ora bisa :( Bener, iku bisa. ora mung obyek utawa teks? Ya, iki set iki katon kaya :) Iki game sing disimpen! Yen kita pengin mulihake obyek asli, yaiku, mbukak lan nerusake game saka ngendi kita mandheg, kita butuh proses mbalikke , deserialization ... Iki bakal katon kaya ing kasus 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{territoriesInfo=[Spanyol duwé 6 provinsi, Rusia duwé 10 provinsi, Prancis duwé 8 provinsi], resourcesInfo=[Spanyol duwé 100 emas, Rusia duwé 80 emas, Prancis duwé 90 emas], diplomasiInfo=[Prancis perang karo Rusia, Spanyol wis manggoni posisi netralitas]} Hebat! Kita bisa pisanan nyimpen negara game kita menyang file, banjur mulihake saka file. Saiki ayo nyoba nglakoni sing padha, nanging mbusak SavedGamepengenal versi saka kelas kita. Kita ora bakal nulis ulang loro kelas kita, kode ing wong-wong mau bakal padha, kita mung SavedGamembusak private static final long serialVersionUID. Punika obyek kita sawise serialization: ¬н sr SavedGameі€MіuОm‰ [ diplomacyInfot [Ljava/lang/String;[ resourcesInfoq ~ [ territoriesInfoq ~ xpur [Ljava.lang.String;ТВзй{G xp t pФравРССРї ‚ СЃ РуссЃСЃРёРµР№, СЃРїР°Русский. "РЈ Р˜СЃРї ании 100 Р · Basa Inggris dasanama saka Basa Inggris : 80            ёРё 6 R 10 10 ѕРІРІРёРЅС†РёРЅА Lan nalika nyoba deserialize, iki kedadeyan: InvalidClassException: kelas lokal ora kompatibel: stream classdesc serialVersionUID = - 196410440475012755, kelas lokal serialVersionUID = -6675950253085108747 Iki minangka pangecualian sing padha sing kasebut ing ndhuwur. Sampeyan bisa maca liyane babagan iki ing artikel saka salah sawijining siswa. Miturut cara, kita ora kejawab siji titik penting. Cetha yen strings lan primitif gampang serialized: Jawa mesthi wis sawetara- banjur ana mekanisme dibangun ing iki. Nanging apa yen serializable-class kita duwe lapangan sing ditulis ora minangka primitif, nanging minangka referensi kanggo obyek liyane? Ayo, contone , nggawe kelas kapisah TerritoriesInfokanggo nggarap kelas kita . ResourcesInfoDiplomacyInfoSavedGame

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 + '\'' +
               '}';
   }
}
Nanging saiki kita duwe pitakonan: kudu kabeh kelas iki Serializable yen kita pengin serialize kelas diganti SavedGame?

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 mriksa iki ing laku! Ayo ninggalake kabeh kaya saiki lan nyoba kanggo 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
       TerritoriesInfo territoriesInfo = new TerritoriesInfo("Spain has 6 provinces, Russia has 10 provinces, France has 8 provinces");
       ResourcesInfo resourcesInfo = new ResourcesInfo("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 position of neutrality");


       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: Pengecualian ing utas "utama" java.io.NotSerializableException: DiplomacyInfo Gagal! Bener, iki jawaban kanggo pitakonan kita. Nalika sampeyan nggawe serialisasi obyek, kabeh obyek sing dirujuk ing variabel conto bakal dadi serial. Lan yen obyek kasebut uga referensi obyek katelu, padha uga serialized. Lan ing ad infinitum. Kabeh kelas ing chain iki kudu Serializable, digunakake padha ora serializable lan pangecualian bakal di buwang. Iki, kanthi cara, bisa nyebabake masalah ing mangsa ngarep. Apa sing kudu kita lakoni, contone, yen kita ora butuh bagean saka kelas sajrone serialisasi? Utawa, contone, TerritoryInfokita marisi kelas ing program kita minangka bagéan saka sawetara perpustakaan. Nanging, iku ora Serializable, lan, miturut, kita ora bisa ngganti. Pranyata kita ora bisa nambah lapangan TerritoryInfokanggo kelas kita , amarga banjur kabeh kelas bakal dadi non-serializable! Masalah: / Masalah kaya iki ditanggulangi ing basa Jawa nggunakake tembung kunci . Yen sampeyan nambahake tembung kunci iki menyang kolom kelas, nilai kolom iki ora bakal diseralisasi. Ayo dadi nyoba kanggo nggawe salah siji saka kothak kelas kita , sawise kang kita bakal serialize lan mulihake siji obyek. SavedGameSavedGameSerialisasi lan Deserialisasi ing Jawa - 2transientSavedGame transient

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
       TerritoriesInfo territoriesInfo = new TerritoriesInfo("Spain has 6 provinces, Russia has 10 provinces, France has 8 provinces");
       ResourcesInfo resourcesInfo = new ResourcesInfo("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 position of neutrality");


       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='Spanyol duwe 100 emas, Rusia duwe 80 emas, Prancis duwe 90 emas'}, diplomacyInfo=DiplomacyInfo{info='Prancis perang karo Rusia, Spanyol wis njupuk netralitas posisi'}} Ing wektu sing padha, kita nampa jawaban kanggo pitakonan apa nilai bakal diutus transientkanggo -field. Diwenehi nilai standar. Ing kasus obyek iki null. Ing wektu luang, sampeyan bisa maca artikel sing apik babagan serialisasi iki . Iki uga ngomong babagan antarmuka Externalizable, sing bakal diomongake ing kuliah sabanjure. Kajaba iku, ana bab babagan topik iki ing buku "Kepala-Kawitan Jawa", digatekake :)
Komentar
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION