Apa yang dimaksud dengan Serializable?

136

Apa sebenarnya arti suatu kelas Serializabledi Jawa? Atau secara umum, dalam hal ini ...

Ritwik Bose
sumber
10
@skaffman Inilah yang dikatakan untuk kelas Serializable: Serializability of a class is enabled by the class implementing the java.io.Serializable interface. Classes that do not implement this interface will not have any of their state serialized or deserialized. All subtypes of a serializable class are themselves serializable. The serialization interface has no methods or fields and serves only to identify the semantics of being serializable.
Ritwik Bose
32
Penjelasan yang bagus jika Anda sudah tahu apa arti serial dan deserialized. (Bukan pujian.) Definisi seperti itu membantu Anda memahami masalah dengan lebih baik secara teknis sekali, dan hanya sekali, Anda sudah memiliki pengetahuan tentang hal itu.
Xonatron

Jawaban:

132

Serialisasi adalah mempertahankan objek dari memori ke urutan bit, misalnya untuk disimpan ke disk. Deserialisasi adalah sebaliknya - membaca data dari disk untuk melembabkan / membuat objek.

Dalam konteks pertanyaan Anda, ini adalah antarmuka yang jika diimplementasikan dalam kelas, kelas ini dapat secara otomatis diserialisasi dan diserialisasi oleh berbagai serializer.

Oded
sumber
2
Perhatikan juga bahwa semua bidang yang tidak ditandai secara eksplisit akan serial juga. Ini berarti bahwa Anda dapat menyimpan struktur data yang kompleks dengan mudah hanya dengan membuat serial objek root.
Thorbjørn Ravn Andersen
1
Jadi ketika kita berbicara tentang "Objek", apakah maksud kita objek yang dipakai oleh kelas, atau sembarang "Objek Perangkat Lunak" seperti rakitan, file, dll? Dan jika ini yang terakhir, apakah itu hanya cara standar pengiriman data antara program dan lingkungan?
Sunburst275
1
@ Sunburst275 - dalam hal ini, ini adalah representasi dalam memori dari kelas dalam memori - yaitu instance kelas (tidak ada titik nyata untuk berbicara tentang serialisasi rakitan, karena mereka biasanya pada disk sebagai file yang dapat cukup dikirim sekitar apa adanya).
Oded
44

Meskipun sebagian besar pengguna sudah memberikan jawaban, tetapi saya ingin menambahkan contoh bagi mereka yang membutuhkannya untuk menjelaskan ide:

Katakanlah Anda memiliki orang yang berkelas seperti berikut ini:

public class Person implements java.io.Serializable {
    /**
     * 
     */
    private static final long serialVersionUID = 1L;
    public String firstName;
    public String lastName;
    public int age;
    public String address;

    public void play() {
        System.out.println(String.format(
                "If I win, send me the trophy to this address: %s", address));
    }
    @Override
    public String toString() {
        return String.format(".....Person......\nFirst Name = %s\nLast Name = %s", firstName, lastName);
    }
}

dan kemudian Anda membuat objek seperti ini:

Person william = new Person();
        william.firstName = "William";
        william.lastName = "Kinaan";
        william.age = 26;
        william.address = "Lisbon, Portugal";

Anda bisa membuat serial objek itu ke banyak aliran. Saya akan melakukannya untuk dua aliran:

Serialisasi ke output standar:

public static void serializeToStandardOutput(Person person)
            throws IOException {
        OutputStream outStream = System.out;
        ObjectOutputStream stdObjectOut = new ObjectOutputStream(outStream);
        stdObjectOut.writeObject(person);
        stdObjectOut.close();
        outStream.close();
    }

Serialisasi ke file:

public static void serializeToFile(Person person) throws IOException {
        OutputStream outStream = new FileOutputStream("person.ser");
        ObjectOutputStream fileObjectOut = new ObjectOutputStream(outStream);
        fileObjectOut.writeObject(person);
        fileObjectOut.close();
        outStream.close();
    }

Kemudian:

Deserialisasi dari file:

public static void deserializeFromFile() throws IOException,
            ClassNotFoundException {
        InputStream inStream = new FileInputStream("person.ser");
        ObjectInputStream fileObjectIn = new ObjectInputStream(inStream);
        Person person = (Person) fileObjectIn.readObject();
        System.out.println(person);
        fileObjectIn.close();
        inStream.close();
    }
William Kinaan
sumber
Terima kasih. Saya pikir saya mengerti sekarang.
Sunburst275
40

Ini berarti instance kelas dapat diubah menjadi byte-stream (misalnya, untuk disimpan ke file) dan kemudian dikonversi kembali ke kelas lagi. Pemuatan ulang ini dapat terjadi pada instance program yang berbeda, atau bahkan pada mesin yang berbeda. Serialisasi (dalam bahasa apa pun) melibatkan semua jenis masalah, terutama ketika Anda memiliki referensi ke objek lain di dalam serialisable.

David
sumber
15

Berikut adalah penjelasan rinci tentang Serialisasi : (blog saya sendiri)

Serialisasi:

Serialisasi adalah proses serialisasi keadaan suatu objek direpresentasikan dan disimpan dalam bentuk urutan byte. Ini dapat disimpan dalam file. Proses untuk membaca keadaan objek dari file dan mengembalikannya disebut deserialization.

Apa perlunya Serialisasi?

Dalam arsitektur modern, selalu ada kebutuhan untuk menyimpan keadaan objek dan kemudian mengambilnya. Sebagai contoh di Hibernate, untuk menyimpan objek kita harus membuat kelas Serializable. Apa yang dilakukannya, adalah bahwa begitu keadaan objek disimpan dalam bentuk byte, ia dapat ditransfer ke sistem lain yang kemudian dapat membaca dari keadaan dan mengambil kelas. Status objek dapat berasal dari database atau jvm yang berbeda atau dari komponen terpisah. Dengan bantuan Serialisasi kami dapat mengambil status Objek.

Contoh Kode dan penjelasan:

Pertama mari kita lihat di Kelas Item:

public class Item implements Serializable{

    /**
    *  This is the Serializable class
    */
    private static final long serialVersionUID = 475918891428093041L;
    private Long itemId;
    private String itemName;
    private transient Double itemCostPrice;
    public Item(Long itemId, String itemName, Double itemCostPrice) {
        super();
        this.itemId = itemId;
        this.itemName = itemName;
        this.itemCostPrice = itemCostPrice;
      }

      public Long getItemId() {
          return itemId;
      }

     @Override
      public String toString() {
          return "Item [itemId=" + itemId + ", itemName=" + itemName + ", itemCostPrice=" + itemCostPrice + "]";
       }


       public void setItemId(Long itemId) {
           this.itemId = itemId;
       }

       public String getItemName() {
           return itemName;
       }
       public void setItemName(String itemName) {
            this.itemName = itemName;
        }

       public Double getItemCostPrice() {
            return itemCostPrice;
        }

        public void setItemCostPrice(Double itemCostPrice) {
             this.itemCostPrice = itemCostPrice;
        }
}

Dalam kode di atas dapat dilihat bahwa kelas Item mengimplementasikan Serializable .

Ini adalah antarmuka yang memungkinkan kelas menjadi serializable.

Sekarang kita bisa melihat variabel yang disebut serialVersionUID diinisialisasi ke variabel Long. Angka ini dihitung oleh kompiler berdasarkan status kelas dan atribut kelas. Ini adalah angka yang akan membantu jvm mengidentifikasi keadaan suatu objek ketika membaca keadaan objek dari file.

Untuk itu kita bisa melihat di Dokumentasi Oracle resmi:

Runtime serialisasi mengaitkan dengan setiap kelas seri dengan nomor versi, yang disebut serialVersionUID, yang digunakan selama deserialisasi untuk memverifikasi bahwa pengirim dan penerima objek serial telah memuat kelas untuk objek yang kompatibel dengan serialisasi. Jika penerima telah memuat kelas untuk objek yang memiliki serialVersionUID berbeda dari kelas pengirim yang sesuai, maka deserialisasi akan menghasilkan InvalidClassException. Kelas serializable dapat mendeklarasikan serialVersionUID sendiri secara eksplisit dengan mendeklarasikan bidang bernama "serialVersionUID" yang harus statis, final, dan bertipe panjang: ANY-ACCESS-MODIFIER static final long serialVersionUID = 42L; Jika kelas serializable tidak secara eksplisit mendeklarasikan serialVersionUID, maka runtime serialisasi akan menghitung nilai serialVersionUID default untuk kelas yang didasarkan pada berbagai aspek kelas, seperti yang dijelaskan dalam Spesifikasi Serialisasi Objek Java (TM). Namun, sangat disarankan bahwa semua kelas serializable secara eksplisit mendeklarasikan nilai serialVersionUID, karena perhitungan serialVersionUID default sangat sensitif terhadap detail kelas yang dapat bervariasi tergantung pada implementasi kompiler, dan dengan demikian dapat menghasilkan InvalidClassExceptions yang tidak terduga selama deserialisasi. Oleh karena itu, untuk menjamin nilai serialVersionUID yang konsisten di seluruh implementasi java compiler yang berbeda, kelas serial harus mendeklarasikan nilai serialVersionUID yang eksplisit. Juga sangat disarankan bahwa deklarasi serialVersionUID eksplisit menggunakan pengubah pribadi jika memungkinkan,

Jika Anda perhatikan ada kata kunci lain yang kami gunakan yang sementara .

Jika suatu bidang tidak serializable, itu harus ditandai sementara. Di sini kami menandai itemCostPrice sebagai sementara dan tidak ingin itu ditulis dalam file

Sekarang mari kita lihat bagaimana cara menulis status suatu objek dalam file dan kemudian membacanya dari sana.

public class SerializationExample {

    public static void main(String[] args){
        serialize();
       deserialize();
    } 

    public static void serialize(){

         Item item = new Item(1L,"Pen", 12.55);
         System.out.println("Before Serialization" + item);

         FileOutputStream fileOut;
         try {
             fileOut = new FileOutputStream("/tmp/item.ser");
             ObjectOutputStream out = new ObjectOutputStream(fileOut);
             out.writeObject(item);
             out.close();
             fileOut.close();
             System.out.println("Serialized data is saved in /tmp/item.ser");
           } catch (FileNotFoundException e) {

                  e.printStackTrace();
           } catch (IOException e) {

                  e.printStackTrace();
           }
      }

    public static void deserialize(){
        Item item;

        try {
                FileInputStream fileIn = new FileInputStream("/tmp/item.ser");
                ObjectInputStream in = new ObjectInputStream(fileIn);
                item = (Item) in.readObject();
                System.out.println("Serialized data is read from /tmp/item.ser");
                System.out.println("After Deserialization" + item);
        } catch (FileNotFoundException e) {
                e.printStackTrace();
        } catch (IOException e) {
               e.printStackTrace();
        } catch (ClassNotFoundException e) {
               e.printStackTrace();
        }
     }
}

Pada contoh di atas kita dapat melihat contoh serialisasi dan deserialisasi objek.

Untuk itu kami menggunakan dua kelas. Untuk membuat serial objek, kami telah menggunakan ObjectOutputStream. Kami telah menggunakan metode writeObject untuk menulis objek dalam file.

Untuk Deserializing kami telah menggunakan ObjectInputStream yang membaca dari objek dari file. Ini menggunakan readObject untuk membaca data objek dari file.

Output dari kode di atas akan seperti:

Before SerializationItem [itemId=1, itemName=Pen, itemCostPrice=12.55]
Serialized data is saved in /tmp/item.ser
After DeserializationItem [itemId=1, itemName=Pen, itemCostPrice=null]

Perhatikan bahwa itemCostPrice dari objek deserialized adalah null karena tidak ditulis.

Pritam Banerjee
sumber
2
Terima kasih atas penjelasan terperinci ini.
Promise Preston
Ini penjelasan yang bagus! Terima kasih! Tapi jujur ​​saja, entri ini terlihat jauh lebih bersih daripada yang ada di blog Anda. Bagaimanapun, ini sangat membantu!
Sunburst275
11

Serialisasi melibatkan menyelamatkan keadaan saat ini dari suatu objek ke aliran, dan mengembalikan objek yang setara dari aliran itu. Aliran berfungsi sebagai wadah untuk objek

Jigar Joshi
sumber
1
Definisi ini tampaknya lebih tepat. Terima kasih.
Promise Preston
6

Serializable dipanggil seperti antarmuka tetapi lebih seperti bendera ke subsistem Serialisasi, saat runtime. Dikatakan objek ini bisa diselamatkan. Semua variabel instance Objects dengan pengecualian tidak ada objek serializable dan yang volatile mark akan disimpan.

Bayangkan aplikasi Anda dapat mengubah warna sebagai opsi, tanpa mempertahankan pengaturan eksternal itu Anda harus mengubah warna setiap kali Anda menjalankannya.

AphexMunky
sumber
5
Ini bukan 'flag to the compiler'. Ini adalah flag ke subsistem Serialisasi, pada saat runtime.
Marquis of Lorne
1
@ EJP - Terima kasih, tidak tahu itu
AphexMunky
Dengan hormat, mengapa menulisnya ketika Anda tidak tahu itu benar? Anda juga meninggalkan 'sementara'. Semua dalam semua jawaban yang buruk, maaf.
Marquis of Lorne
19
Jika saya tidak menulisnya, saya tidak akan dikoreksi dan akan menjadi lebih buruk. Semua jawaban lain tidak memberikan jawaban sementara. Anda bahkan tidak menulis jawaban, Anda hanya mengganggu orang lain.
AphexMunky
4

Serialisasi adalah teknik untuk menyimpan atau menulis objek dan data ke file. Dengan menggunakan ObjectOutputStreamdan FileOutputStreamkelas. Kelas-kelas ini memiliki metode khusus untuk bertahan objek. SukawriteObject();

untuk penjelasan yang jelas dengan angka-angka. Lihat Di Sini untuk info lebih lanjut

Mdhar9e
sumber
2

Untuk mempresentasikan dari perspektif lain. Serialisasi adalah sejenis antarmuka yang disebut 'antarmuka penanda'. Antarmuka penanda adalah antarmuka yang tidak mengandung deklarasi metode, tetapi hanya menunjuk (atau "menandai") kelas yang mengimplementasikan antarmuka sebagai memiliki beberapa properti. Jika Anda memahami polimorfisme, ini akan sangat masuk akal. Dalam kasus antarmuka penanda Serializable, metode ObjectOutputStream.write (Objek) akan gagal jika argumennya tidak mengimplementasikan antarmuka. Ini adalah kesalahan potensial di java, bisa saja ObjectOutputStream.write (Serializable)

Sangat Dianjurkan: Membaca Item 37 dari Java Efektif oleh Joshua Bloch untuk mempelajari lebih lanjut.

nanospeck
sumber
2

Serialisasi: Menulis Status Objek ke File / Jaringan atau di mana saja. (Mean Java Object bentuk yang didukung ke File formulir yang didukung atau bentuk jaringan yang didukung)

Deserialisasi: Status Pembacaan Objek dari File / Jaringan atau di mana saja. (Mean File / Jaringan Didukung formulir ke Java Didukung Formulir)

Asif Mushtaq
sumber
1

Hanya untuk menambah jawaban lain dan berkaitan dengan generalitas. Serialisasi terkadang dikenal sebagai pengarsipan, misalnya dalam Objective-C.

Greg Sexton
sumber