Serileştirilebilir ne anlama geliyor?


136

Bir sınıfın SerializableJava'da olması tam olarak ne anlama geliyor ? Veya genel olarak, bu konuda ...


10
@skaffman Sınıf için söyledikleri 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
Serileştirilmiş ve serileştirilmiş öğelerin ne anlama geldiğini zaten biliyorsanız harika bir açıklama. (Bir iltifat değil.) Bu tür tanımlar, sorunu teknik olarak bir kez daha iyi anlamanıza yardımcı olur ve sadece bir kez, zaten bu konuda biraz bilginiz vardır.
Xonatron

Yanıtlar:


132

Serileştirme , örneğin diske kaydetmek için bir nesneyi bellekten bir bit dizisine kadar sürdürmektedir. Deserialization tam tersidir - bir nesneyi hidratlamak / oluşturmak için diskten veri okumaktır.

Sorunuz bağlamında, bir sınıfta uygulandığında bu sınıfın farklı serileştiriciler tarafından otomatik olarak serileştirilebileceği ve serileştirilebileceği bir arabirimdir.


2
Ayrıca, aksi belirtilmedikçe tüm alanların da serileştirileceğini unutmayın. Bu, yalnızca kök nesneyi serileştirerek karmaşık bir veri yapısını kolayca kaydedebileceğiniz anlamına gelir.
Thorbjørn Ravn Andersen

1
"Nesneler" den bahsederken, bir sınıf tarafından başlatılan nesneyi mi yoksa yalnızca derlemeler, dosyalar vb. Gibi herhangi bir "Yazılım Nesnesi" mi demek istiyoruz? İkincisi ise, programlar ve ortamlar arasında veri göndermenin standart bir yolu mu?
Sunburst275

1
@ Sunburst275 - bu durumda, bu bellekte bir sınıfın bellek temsilidir - yani bir sınıf örneği (genellikle diskte bulunan dosyalar olarak disklerde oldukları için derlemelerin serileştirilmesi hakkında konuşmanın gerçek bir anlamı yoktur. basitçe olduğu gibi gönderilebilir).
Oded

44

Kullanıcıların çoğu zaten cevabı vermiş olsa da, fikri açıklamak için buna ihtiyaç duyanlar için bir örnek eklemek istiyorum:

Diyelim ki aşağıdaki gibi bir sınıf kişiniz var:

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);
    }
}

ve sonra böyle bir nesne oluşturursunuz:

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

Bu nesneyi birçok akışa serileştirebilirsiniz. Bunu iki akıma yapacağım:

Standart çıktıya seri hale getirme:

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

Bir dosyanın seri hale getirilmesi:

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();
    }

Sonra:

Dosyadan serisini kaldırma:

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();
    }

Teşekkür ederim. Sanırım şimdi anladım.
Sunburst275

40

Sınıf örneklerinin bir bayt akışına dönüştürülebileceği (örneğin, bir dosyaya kaydedilecek) ve daha sonra tekrar sınıflara dönüştürülebileceği anlamına gelir. Bu yeniden yükleme, programın farklı bir örneğinde veya hatta farklı bir makinede gerçekleşebilir. Serileştirme (herhangi bir dilde), özellikle serileştirilebilir nesnenin içindeki diğer nesnelere referansınız olduğunda, her türlü sorunu içerir.


15

İşte Serileştirmenin ayrıntılı bir açıklaması : (kendi blogum)

Serile:

Serileştirme, bir nesnenin durumunun serileştirilmesi işlemidir, bir bayt dizisi şeklinde temsil edilir ve saklanır. Bu bir dosyada saklanabilir. Nesnenin durumunu dosyadan okuma ve geri yükleme işlemine serileştirme denir.

Serileştirme ihtiyacı nedir?

Günümüz mimarisinde, her zaman nesne durumunun depolanmasına ve daha sonra geri alınmasına ihtiyaç vardır. Örneğin Hazırda Bekletme modunda, bir nesneyi saklamak için Serializable sınıfını yapmalıyız. Yaptığı şey, nesne durumu bayt biçiminde kaydedildikten sonra, durumdan okuyabilen ve sınıfı alabilen başka bir sisteme aktarılabilmesidir. Nesne durumu bir veritabanından veya farklı bir jvm'den veya ayrı bir bileşenden gelebilir. Serileştirme yardımıyla Nesne durumunu alabiliriz.

Kod Örnek ve açıklama:

Önce Item Class'a bir göz atalım:

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;
        }
}

Yukarıdaki kodda Item sınıfının Serializable uyguladığı görülebilir .

Bu, bir sınıfın serileştirilebilmesini sağlayan arabirimdir.

Artık serialVersionUID adlı bir değişkenin Long değişkenine başlatıldığını görebiliriz . Bu sayı, derleyici tarafından sınıfın durumuna ve sınıf özniteliklerine göre hesaplanır. Bu, jvm'nin nesnenin durumunu dosyadan okuduğunda bir nesnenin durumunu tanımlamasına yardımcı olacak sayıdır.

Bunun için resmi Oracle Dokümantasyonuna bakabiliriz:

Serileştirme çalışma zamanı, serileştirilebilir her sınıfla, serileştirme sırasında serileştirilmiş bir nesnenin göndericisinin ve alıcısının serileştirme ile uyumlu olan bu nesne için yüklü sınıflara sahip olduğunu doğrulamak için kullanılan serialVersionUID adı verilen bir sürüm numarasını ilişkilendirir. Alıcı, karşılık gelen gönderenin sınıfından farklı bir serialVersionUID değerine sahip nesne için bir sınıf yüklediyse, serileştirme işlemi InvalidClassException özelliğine neden olur. Serileştirilebilir bir sınıf, statik, son ve uzun tür olması gereken "serialVersionUID" adlı bir alanı bildirerek kendi serialVersionUID değerini açıkça bildirebilir: ANY-ACCESS-MODIFIER statik final uzun serialVersionUID = 42L; Serileştirilebilir bir sınıf bir serialVersionUID'yi açıkça bildirmezse, serileştirme çalışma zamanı, Java (TM) Nesne Serileştirme Belirtimi'nde açıklandığı gibi, sınıfın çeşitli yönlerine dayalı olarak bu sınıf için varsayılan bir serialVersionUID değeri hesaplar. Ancak, varsayılan serialVersionUID hesaplaması derleyici uygulamalarına bağlı olarak değişebilen ve bu nedenle serileştirme sırasında beklenmedik InvalidClassExceptions ile sonuçlanabilecek sınıf ayrıntılarına karşı çok hassas olduğundan, tüm serileştirilebilir sınıfların açıkça serialVersionUID değerlerini bildirmesi şiddetle önerilir. Bu nedenle, farklı java derleyici uygulamalarında tutarlı bir serialVersionUID değerini garanti etmek için, serileştirilebilir bir sınıfın açık bir serialVersionUID değeri bildirmesi gerekir. Ayrıca, açık serialVersionUID bildirimlerinin mümkün olduğunda özel değiştiriciyi kullanması önemle tavsiye edilir.

Geçici olarak kullandığımız başka bir anahtar kelime olduğunu fark ettiyseniz .

Bir alan serileştirilemezse, geçici olarak işaretlenmelidir. Burada itemCostPrice'ı geçici olarak işaretledik ve bir dosyaya yazılmasını istemiyoruz

Şimdi bir nesnenin durumunu dosyaya nasıl yazacağımıza ve daha sonra oradan okuyalım.

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();
        }
     }
}

Yukarıda bir nesnenin serileştirme ve serileştirme örneğini görebiliriz.

Bunun için iki sınıf kullandık. Nesneyi serileştirmek için ObjectOutputStream kullandık. Nesneyi dosyaya yazmak için writeObject yöntemini kullandık.

Diziselleştirmeyi kaldırmak için, dosyadan nesneden okunan ObjectInputStream öğesini kullandık. Nesne verilerini dosyadan okumak için readObject kullanır.

Yukarıdaki kodun çıktısı şöyle olacaktır:

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]

Deserialized nesneden itemCostPrice'ın yazılmadığı için boş olduğuna dikkat edin .


2
Bu ayrıntılı açıklama için teşekkür ederim.
Promise Preston

Bu güzel bir açıklama! Teşekkür ederim! Ama dürüst olmak gerekirse, bu giriş blogunuzdakinden çok daha temiz görünüyor. Her neyse, bu çok yardımcı oldu!
Sunburst275

11

Diziselleştirme, bir nesnenin geçerli durumunu bir akışa kaydetmeyi ve bu akıştan eşdeğer bir nesneyi geri yüklemeyi içerir. Akış, nesne için bir kap işlevi görür


1
Bu tanım daha kesin görünüyor. Teşekkür ederim.
Promise Preston

6

Serileştirilebilir bir arayüz gibi çağrılır, ancak daha çok Serileştirme alt sistemine bir çalışma zamanında benzer. Bu nesnenin kaydedilebileceğini söylüyor. Serileştirilemeyen nesneler ve uçucu işareti olanlar hariç tüm Objeler örnek değişkenleri kaydedilir.

Uygulamanızın isteğe bağlı olarak renk değiştirebileceğini düşünün, bu ayarı harici tutmadan her çalıştırdığınızda rengi değiştirmeniz gerekir.


5
Bu bir 'derleyiciye bayrak' değildir. Bu, Serileştirme alt sisteminin çalışma zamanında bir işaretidir.
Lorne Marquis

1
@EJP - Teşekkürler, bunu bilmiyordum
AphexMunky

Saygı ile, doğru olduğunu bilmediğinizde neden yazıyorsunuz? Ayrıca 'geçici' kalmayı da bıraktınız. Sonuçta kötü bir cevap, özür dilerim.
Lorne Marquis

19
Yazmasaydım düzeltilmezdim ve daha da kötüsü olurdum. Diğer tüm cevaplar da geçici olarak kaldı. Bir cevap bile yazmadınız, sadece diğer insanları trollediyorsunuz.
AphexMunky

4

Serileştirme, nesneleri ve verileri dosyalara kaydetme veya yazma tekniğidir. Kullanarak ObjectOutputStreamve FileOutputStreamsınıflar. Bu sınıflar nesneleri devam ettirmek için özel yöntemlere sahiptir. sevmekwriteObject();

rakamlarla net bir açıklama için. Daha fazla bilgi için buraya bakın


2

Başka bir açıdan sunmak. Serileştirme, 'işaretleyici arabirimi' adı verilen bir tür arabirimdir. İşaretleyici arabirimi, yöntem bildirimi içermeyen, yalnızca arabirimi bazı özelliklere sahip olarak uygulayan bir sınıfı belirten (veya "işaretler") bir arabirimdir. Eğer polimorfizmi anlarsanız bu çok mantıklı olacaktır. Serileştirilebilir işaretleyici arabirimi durumunda, bağımsız değişkeni arabirimi uygulamazsa ObjectOutputStream.write (Object) yöntemi başarısız olur. Bu, java'da olası bir hatadır, ObjectOutputStream.write (Serializable) olabilir

Şiddetle Tavsiye Edilir: Daha fazla bilgi edinmek için Joshua Bloch'un Etkili Java'dan 37. Maddesini okuma .


2

Serileştirme: Nesnenin Durumunu Dosyaya / Ağa veya herhangi bir yere yazma. (Desteklenen Form veya Ağ Destekli Form için Ortalama Java Nesnesi Desteklenen form)

Deserialization: Nesnenin Durumunu Dosyadan / Ağdan veya herhangi bir yerden okuma. (Java Nesnesi Destekli Form için Ortalama Dosya / Ağ Destekli form)


1

Sadece diğer cevaplara ve genelliğe ilişkin olarak. Serileştirme bazen arşivleme olarak bilinir, örneğin Objective-C'de.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.