CodeGym/Java Blog/Acak/Apa perbedaan antara serialisasi dan deserialisasi di Jaw...
John Squirrels
Level 41
San Francisco

Apa perbedaan antara serialisasi dan deserialisasi di Jawa?

Dipublikasikan di grup Acak
anggota
Hai! Dalam pelajaran hari ini, kita berbicara tentang serialisasi dan deserialisasi di Java. Kita akan mulai dengan contoh sederhana. Katakanlah Anda telah membuat game komputer. Jika Anda tumbuh di tahun 90-an dan mengingat konsol game pada masa itu, Anda mungkin tahu bahwa mereka kekurangan sesuatu yang kita anggap remeh hari ini - kemampuan untuk menyimpan dan memuat game :) Jika tidak, bayangkan itu! Apa perbedaan antara serialisasi dan deserialisasi di Jawa?  - 1 Saya khawatir hari ini game tanpa kemampuan ini akan hancur! Apa artinya "menyimpan" dan "memuat" game? Nah, kami memahami arti biasa: kami ingin melanjutkan permainan dari tempat kami tinggalkan. Untuk melakukan ini, kami membuat semacam "titik pemeriksaan", yang kemudian kami gunakan untuk memuat game. Tapi apa artinya ini bagi seorang programmer daripada gamer biasa? Jawabannya sederhana: kita'. Katakanlah Anda bermain sebagai Spanyol di Strategium. Gim Anda memiliki negara: siapa yang memiliki wilayah mana, siapa yang memiliki berapa banyak sumber daya, siapa bersekutu dengan siapa, siapa berperang dengan siapa, dan seterusnya. Kami entah bagaimana harus menyimpan informasi ini, status program kami, untuk memulihkannya di masa mendatang dan melanjutkan permainan. Karena inilah tepatnya untuk serialisasi dan deserealisasi . Serialisasi adalah proses menyimpan keadaan objek dalam urutan byte. Deserialisasiadalah proses mengembalikan objek dari byte ini. Objek Java apa pun dapat dikonversi menjadi urutan byte. Mengapa kita membutuhkan itu? Kami telah mengatakan lebih dari sekali bahwa program tidak ada dengan sendirinya. Paling sering, mereka berinteraksi dengan program lain, bertukar data, dll. Dan urutan byte adalah format yang nyaman dan efisien. Sebagai contoh, kita dapat mengubah SavedGameobjek kita menjadi urutan byte, mengirim byte ini melalui jaringan ke komputer lain, dan kemudian di komputer kedua mengubah byte ini kembali menjadi objek Java! Kedengarannya sulit, bukan? Dan menerapkan proses ini sepertinya menyusahkan:/ Untungnya, tidak demikian! :) Di Jawa, theSerializableantarmuka bertanggung jawab untuk proses serialisasi. Antarmuka ini sangat sederhana: Anda tidak perlu mengimplementasikan satu metode pun untuk menggunakannya! Ini adalah betapa sederhananya tampilan kelas hemat game kami:
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) +
               '}';
   }
}
Tiga larik bertanggung jawab atas informasi tentang wilayah, sumber daya, dan diplomasi. Antarmuka Serializable memberi tahu mesin virtual Java: " Semuanya baik-baik saja — jika perlu, objek kelas ini dapat diserialisasi ". Antarmuka tanpa antarmuka tunggal terlihat aneh :/ Mengapa perlu? Jawaban atas pertanyaan ini dapat dilihat di atas: ini hanya berfungsi untuk memberikan informasi yang diperlukan ke mesin virtual Java. Dalam salah satu pelajaran kami sebelumnya, kami secara singkat menyebutkan antarmuka penanda . Ini adalah antarmuka informasi khusus yang menandai kelas kami dengan informasi tambahan yang akan berguna untuk mesin Java di masa mendatang. Mereka tidak memiliki metode apa pun yang harus Anda terapkan.Serializableadalah salah satu antarmuka tersebut. Poin penting lainnya: Mengapa kita membutuhkan private static final long serialVersionUIDvariabel yang kita definisikan di kelas? Mengapa itu dibutuhkan? Bidang ini berisi pengidentifikasi unik untuk versi kelas serial . Setiap kelas yang mengimplementasikan Serializableantarmuka memiliki versionpengenal. Itu dihitung berdasarkan konten kelas: bidangnya, urutan deklarasinya, metode, dll. Jika kita mengubah jenis bidang dan/atau jumlah bidang di kelas kita, maka pengidentifikasi versi segera berubah . serialVersionUIDjuga ditulis ketika kelas diserialkan. Saat kami mencoba melakukan deserialize, yaitu memulihkan objek dari sekumpulan byte, yang terkait serialVersionUIDdibandingkan dengan nilaiserialVersionUIDuntuk kelas dalam program kami. Jika nilainya tidak cocok, maka java.io. InvalidClassException akan dilempar. Kita akan melihat contohnya di bawah ini. Untuk menghindari hal ini, kami cukup mengatur pengidentifikasi versi secara manual di kelas kami. Dalam kasus kami, itu hanya akan sama dengan 1 (tetapi Anda dapat mengganti nomor lain yang Anda suka). Nah, saatnya untuk mencoba membuat SavedGameobjek kita bersambung dan lihat apa yang terjadi!
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();
   }
}
Seperti yang Anda lihat, kami membuat 2 aliran: FileOutputStreamdan ObjectOutputStream. Yang pertama dapat menulis data ke file, dan yang kedua mengubah objek menjadi byte. Anda telah melihat konstruksi "bersarang" yang serupa, misalnya, new BufferedReader(new InputStreamReader(...)), di pelajaran sebelumnya, jadi itu tidak akan membuat Anda takut :) Dengan membuat "rantai" dua aliran seperti itu, kami melakukan kedua tugas: kami mengubah objek SavedGamemenjadi satu set byte dan simpan ke file menggunakan writeObject()metode ini. Dan, omong-omong, kami bahkan tidak melihat apa yang kami dapatkan! Saatnya untuk melihat file! *Catatan: Anda tidak perlu membuat file terlebih dahulu. Jika file dengan nama itu tidak ada, itu akan dibuat secara otomatis* Dan ini isinya!
¬н 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 :( Tampaknya program kami tidak berfungsi :( Sebenarnya, itu berhasil. Anda ingat bahwa kami mengirim satu set byte, bukan hanya objek atau teks, ke file? Nah, ini apa itu set byte terlihat seperti :) Ini adalah permainan kami yang disimpan! Jika kami ingin mengembalikan objek asli kami, yaitu memulai dan melanjutkan permainan di mana kami tinggalkan, maka kami memerlukan proses sebaliknya: deserialization . Ini akan terlihat seperti di 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);
   }
}
Dan inilah hasilnya!
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]}
Bagus sekali! Kami berhasil menyimpan status game kami terlebih dahulu ke file, lalu memulihkannya dari file tersebut. Sekarang mari kita coba melakukan hal yang sama, tetapi tanpa pengidentifikasi versi untuk SavedGamekelas kita. Kami tidak akan menulis ulang kedua kelas kami. Kode mereka akan tetap sama, tetapi kami akan menghapusnya private static final long serialVersionUIDdari SavedGamekelas. Inilah objek kami setelah serialisasi:
¬н 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 провинций
Tapi lihat apa yang terjadi saat kami mencoba melakukan deserialize:
InvalidClassException: local class incompatible: stream classdesc serialVersionUID = -196410440475012755, local class serialVersionUID = -6675950253085108747
Ini adalah pengecualian yang kami sebutkan di atas. Ngomong-ngomong, kami melewatkan sesuatu yang penting. Masuk akal bahwa String dan primitif dapat dengan mudah diserialkan: Java mungkin memiliki semacam mekanisme bawaan untuk melakukan ini. Tetapi bagaimana jika serializablekelas kita memiliki bidang yang bukan primitif, melainkan referensi ke objek lain? Sebagai contoh, mari buat kelas TerritoriesInfo, ResourcesInfodan DiplomacyInfoterpisah untuk bekerja dengan 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 + '\'' +
               '}';
   }
}
Dan sekarang muncul pertanyaan: apakah semua kelas ini perlu Serializablejika kita ingin membuat serial SavedGamekelas kita yang diubah?
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 +
               '}';
   }
}
Baiklah, mari kita uji! Mari biarkan semuanya apa adanya dan coba buat cerita bersambung sebuah SavedGameobjek:
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();
   }
}
Hasil:
Exception in thread "main" java.io.NotSerializableException: DiplomacyInfo
Itu tidak berhasil! Pada dasarnya, itulah jawaban atas pertanyaan kami. Ketika sebuah objek diserialkan, semua objek yang direferensikan oleh variabel instannya diserialkan. Dan jika objek tersebut juga mereferensikan objek lain, maka objek tersebut juga akan diserialisasikan. Dan seterusnya hingga tak terbatas. Semua kelas dalam rantai ini harusSerializable , jika tidak maka tidak mungkin untuk membuat cerita bersambung dan pengecualian akan dilemparkan. Ngomong-ngomong, ini bisa menimbulkan masalah di jalan. Apa yang harus kita lakukan jika, misalnya, kita tidak memerlukan bagian dari kelas saat membuat cerita bersambung? Atau, misalnya, bagaimana jika TerritoryInfokelas datang kepada kami sebagai bagian dari perpustakaan pihak ketiga. Dan misalkan lebih jauh bahwa itu bukan Serializabledan, karenanya, kita tidak dapat mengubahnya. Ternyata kita tidak bisa menambahkan TerritoryInfofield ke kitaSavedGamekelas, karena melakukan hal itu akan membuat seluruh SavedGamekelas tidak dapat diserialisasi! Itu masalah :/ Apa perbedaan antara serialisasi dan deserialisasi di Jawa?  - 2Di Java, masalah semacam ini diselesaikan dengan menggunakan transientkata kunci. Jika Anda menambahkan kata kunci ini ke bidang kelas Anda, maka bidang itu tidak akan diserialisasi. Mari kita coba membuat salah satu SavedGamebidang instance kelas menjadi sementara. Kemudian kami akan membuat cerita bersambung dan memulihkan satu objek.
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();


   }
}
Dan inilah hasilnya:
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'}}
Selain itu, kami mendapat jawaban atas pertanyaan kami tentang nilai apa yang diberikan ke suatu transientbidang. Itu akan diberi nilai default. Untuk objek, ini adalah null. Anda dapat membaca artikel luar biasa ini tentang serialisasi saat Anda memiliki waktu luang beberapa menit. Itu juga menyebutkan Externalizableantarmuka, yang akan kita bicarakan di pelajaran selanjutnya. Selain itu, buku "Head-First Java" memiliki bab tentang topik ini. Berikan sedikit perhatian :)
Komentar
  • Populer
  • Baru
  • Lama
Anda harus login untuk memberikan komentar
Halaman ini belum memiliki komentar