Nesne serileştirmesi nedir?


Yanıtlar:


400

Serileştirme, bir nesnenin bir dizi bayta dönüştürülmesidir, böylece nesne kolayca kalıcı depolamaya kaydedilebilir veya bir iletişim bağlantısı üzerinden akış yapılabilir. Bayt akışı serileştirilebilir - orijinal nesnenin bir kopyasına dönüştürülebilir.


16
bu zorunlu mu? göndermeden önce seri hale getirmem gerekir mi? hangi biçime dönüştürülür?
Francisco Corrales Morales

15
@FranciscoCorralesMorales - Perde arkasında, tüm veriler bir akış üzerinden gönderilmeden önce serileştirilir. Ne kadar yapmanız ve hangi formatta olacağınız, kullandığınız platforma ve kütüphanelere bağlıdır.
TarkaDaal

3
@FranciscoCorralesMorales Nasıl söylüyorsun? yani formatın platforma ve kütüphaneye bağlı olduğunu söylüyorum. Gerçekten formatı bilmek istiyorum.
JAVA

1
Sadece nesneler için geçerli midir? Değişkenleri serileştirebilir miyiz (nesne kullanmadan bildirilir)?
19'da Rumado

@Rumado Yalnızca nesneler
anKotliner

395

Serileştirmeyi bir nesne örneğini bayt dizisine dönüştürme işlemi olarak düşünebilirsiniz (bu, uygulamaya bağlı olarak ikili olabilir veya olmayabilir).

Bir nesne verisini ağ üzerinden, örneğin bir JVM'den diğerine iletmek istediğinizde çok kullanışlıdır.

Java'da, serileştirme mekanizması platforma yerleştirilmiştir, ancak bir nesneyi serileştirilebilir hale getirmek için Serializable arabirimini uygulamanız gerekir .

Özniteliği geçici olarak işaretleyerek nesnenizdeki bazı verilerin serileştirilmesini de önleyebilirsiniz .

Son olarak, varsayılan mekanizmayı geçersiz kılabilir ve kendi mekanizmanızı sağlayabilirsiniz; bu bazı özel durumlarda uygun olabilir. Bunu yapmak için, java'daki gizli özelliklerden birini kullanırsınız .

Serileştirilen şeyin sınıf tanımı değil, nesnenin veya içeriğin "değeri" olduğunu fark etmek önemlidir. Bu nedenle yöntemler serileştirilmez.

Okumasını kolaylaştırmak için yorumları olan çok temel bir örnek:

import java.io.*;
import java.util.*;

// This class implements "Serializable" to let the system know
// it's ok to do it. You as programmer are aware of that.
public class SerializationSample implements Serializable {

    // These attributes conform the "value" of the object.

    // These two will be serialized;
    private String aString = "The value of that string";
    private int    someInteger = 0;

    // But this won't since it is marked as transient.
    private transient List<File> unInterestingLongLongList;

    // Main method to test.
    public static void main( String [] args ) throws IOException  { 

        // Create a sample object, that contains the default values.
        SerializationSample instance = new SerializationSample();

        // The "ObjectOutputStream" class has the default 
        // definition to serialize an object.
        ObjectOutputStream oos = new ObjectOutputStream( 
                               // By using "FileOutputStream" we will 
                               // Write it to a File in the file system
                               // It could have been a Socket to another 
                               // machine, a database, an in memory array, etc.
                               new FileOutputStream(new File("o.ser")));

        // do the magic  
        oos.writeObject( instance );
        // close the writing.
        oos.close();
    }
}

Bu programı çalıştırdığımızda, "o.ser" dosyası oluşturulur ve arkasında ne olduğunu görebiliriz.

: SomeInteger değerini örneğin Integer.MAX_VALUE olarak değiştirirsek , farkın ne olduğunu görmek için çıktıyı karşılaştırabiliriz.

İşte tam olarak bu farkı gösteren bir ekran görüntüsü:

alternatif metin

Farkları tespit edebilir misiniz? ;)

Java serileştirmesinde ek bir ilgili alan var: serialversionUID ama sanırım bu zaten onu kapsayacak kadar uzun.


1
@ raam86 örneği serileştirilen nesnedir. Ana yöntemde, tür bir nesne oluşturan ayrı bir program olarak düşünebilirsinizSerializationSample
OscarRyz

2
@ raam86 ana yöntemdeki ilk ifadedir: SerializationSample instance = new SerializationSample();daha sonra çıktı oluşturulur ve bu çıktıya yazılan nesne.
OscarRyz

1
Ah. Yeterince yakın folow yoktu. Harika!!
raam86

1
@jacktrades Neden denemiyorsun. Sadece örneği kopyalayın / yapıştırın ve atılan "NotSerializableException" a bakın :)
OscarRyz

1
@jacktrades çünkü bilgisayara nesnenin serileştirilmesine izin verildiği söylenmedi :) oos ne anlama geliyor?
Chris Bennett

101

6 yaşındaki soruyu cevaplamaya cesaret etmek, Java'ya yeni gelen insanlar için çok yüksek bir anlayış eklemek

Serileştirme nedir?

Bir nesneyi bayta dönüştürme

Serileştirme nedir?

Baytları bir nesneye geri dönüştürme (Deserialization).

Serileştirme ne zaman kullanılır?

Nesneye Devam Etmek İstediğimizde. Nesnenin JVM'nin ömrünün ötesinde var olmasını istediğimizde.

Gerçek Dünya Örneği:

ATM: Hesap sahibi, ATM üzerinden sunucudan para çekmeye çalıştığında, para çekme ayrıntıları gibi hesap sahibi bilgileri serileştirilir ve ayrıntıların serileştirilmesi ve işlemleri gerçekleştirmek için kullanıldığı sunucuya gönderilir.

Java'da serileştirme nasıl yapılır.

  1. Uygulama java.io.Serializable(herhangi bir yöntemi uygulamak için çok işaretleyici arayüzü) arayüzü.

  2. Nesneyi sürdürün: Daha java.io.ObjectOutputStreamdüşük düzeyli bir bayt akışının etrafını saran bir filtre akışı olan sınıfı kullanın (Nesneyi dosya sistemlerine yazmak veya düzleştirilmiş bir nesneyi bir ağ kablosu üzerinden aktarmak ve diğer tarafta yeniden oluşturmak).

    • writeObject(<<instance>>) - bir nesne yazmak için
    • readObject() - serileştirilmiş bir Nesneyi okumak için

Hatırlamak:

Bir nesneyi serileştirdiğinizde, nesnenin sınıf dosyası veya yöntemleri değil, yalnızca nesnenin durumu kaydedilir.

2 baytlık bir nesneyi serileştirdiğinizde, 51 bayt serileştirilmiş dosya görürsünüz.

Nesnenin nasıl serileştirildiğini ve serileştirilmesini kaldırma adımları.

Cevap: 51 bayt dosyasına nasıl dönüştü?

  • Önce serileştirme akışı sihirli verilerini yazar (STREAM_MAGIC = "AC ED" ve STREAM_VERSION = JVM sürümü).
  • Daha sonra bir örnekle ilişkili sınıfın meta verilerini yazar (sınıfın uzunluğu, sınıfın adı, serialVersionUID).
  • Sonra üst sınıfın meta verilerini bulana kadar özyinelemeli olarak yazar java.lang.Object.
  • Ardından, örnekle ilişkilendirilmiş gerçek verilerle başlar.
  • Son olarak, meta verilerden başlayarak örnekle ilişkili nesnelerin verilerini gerçek içeriğe yazar.

Java Serialization hakkında daha ayrıntılı bilgi edinmek istiyorsanız lütfen bu bağlantıyı kontrol edin .

Düzenleme : Okumak için iyi bir bağlantı daha .

Bu birkaç sık soruyu cevaplayacaktır:

  1. Sınıftaki herhangi bir alanın serileştirilmemesi.
    Ans: geçici anahtar kelime kullan

  2. Alt sınıf serileştirildiğinde, üst sınıf serileştiriliyor mu?
    Cvp: Hayır, Üst öğe Serileştirilebilir arabirim ebeveynleri alanını genişletmiyorsa serileştirilmez.

  3. Bir üst öğe serileştirildiğinde alt sınıf serileştiriliyor mu?
    Cvp: Evet, varsayılan olarak alt sınıf da serileştirilir.

  4. Alt sınıfın serileştirilmesini nasıl önleyebilirim?
    Ans: a. WriteObject ve readObject yöntemini geçersiz kılın ve atın NotSerializableException.

    b. ayrıca alt sınıftaki tüm alanları geçici olarak işaretleyebilirsiniz.

  5. Thread, OutputStream ve alt sınıfları ve Socket gibi bazı sistem düzeyi sınıfları serileştirilemez.

3
Bu özlü cevap için çok teşekkür ederim, çok yardımcı oldu!
Nobi

21

Serileştirme, bellekte bir "canlı" nesneyi alıp bir yerde (örn. Bellekte, diskte) saklanabilen ve daha sonra tekrar "serileştirilmiş" bir canlı nesneye dönüştürülebilecek bir biçime dönüştürüyor.


14

@OscarRyz'ın sunum şeklini beğendim. Her ne kadar burada @amitgupta tarafından yazılmış olan serileştirme hikayesine devam ediyorum.

Robot sınıfı yapısını bilmek ve serileştirilmiş veriye sahip olsa da, Dünya'nın bilim adamı robotların çalışmasını sağlayabilecek verilerin serileştirilmesini sağlayamadı.

Exception in thread "main" java.io.InvalidClassException:
SerializeMe; local class incompatible: stream classdesc
:

Mars'ın bilim adamları ödemenin tamamını bekliyordu. Ödeme yapıldıktan sonra Mars'ın bilim adamları, serialversionUID'yi Dünya'nın bilim adamları ile paylaştı . Dünya'nın bilim adamı robot sınıfına girdi ve her şey yoluna girdi.


9

Serileştirme, java'da kalıcı nesneler anlamına gelir. Nesnenin durumunu kaydetmek ve durumu daha sonra yeniden oluşturmak istiyorsanız (başka bir JVM'de olabilir) serileştirme kullanılabilir.

Bir nesnenin özelliklerinin yalnızca kaydedileceğini unutmayın. Nesneyi yeniden diriltmek istiyorsanız, sınıf dosyası olmalıdır, çünkü üye değişkenleri üye işlevlerini değil yalnızca depolanır.

Örneğin:

ObjectInputStream oos = new ObjectInputStream(                                 
                                 new FileInputStream(  new File("o.ser")) ) ;
SerializationSample SS = (SearializationSample) oos.readObject();

Searializable, sınıfınızın serileştirilebilir olduğunu gösteren bir işaretleyici arabirimidir. İşaretleyici arabirimi, yalnızca boş bir arabirim olduğu ve bu arabirimin kullanılmasıyla JVM'ye bu sınıfın serileştirilebilir hale getirilebileceğini bildirir.


9

Kendi blogumdan iki sentim:

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

Serile:

Serileştirme, bir nesnenin durumuna devam etme 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 özelliklerine 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, serisini kaldırma 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; Bir serileştirilebilir sınıf açıkça bir serialVersionUID 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şiklik gösterebilecek ve bu nedenle serileştirme sırasında beklenmedik InvalidClassExceptions ile sonuçlanabilecek sınıf ayrıntılarına karşı oldukça hassas olduğundan, tüm serileştirilebilir sınıfların açıkça serialVersionUID değerlerini bildirmesi önemle tavsiye edilir. 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 .

Bu makalenin I. bölümünde Java Serileştirmesinin temellerini zaten tartıştık.

Şimdi derinlemesine ve nasıl çalıştığını tartışalım.

İlk olarak serialversionuid ile başlayalım.

SerialVersionUID bir Serializable sınıftaki bir sürüm kontrolü olarak kullanılır.

Bir serialVersionUID'yi açıkça bildirmezseniz, Serializable sınıfının çeşitli özelliklerine bağlı olarak JVM bunu sizin için otomatik olarak yapar.

Java'nın serialversionuid Hesaplama Algoritması (Daha fazla bilgiyi buradan okuyabilirsiniz)

  1. Sınıf adı.
    1. 32 bit tam sayı olarak yazılan sınıf değiştiricileri.
    2. Her arabirimin adı ada göre sıralanır.
    3. Sınıfın alan adına göre sıralanmış her alanı için (özel statik ve özel geçici alanlar hariç: Alanın adı. 32 bit tam sayı olarak yazılan alanın değiştiricileri. Alanın tanımlayıcısı.
    4. Sınıf başlatıcısı varsa, aşağıdakileri yazın: Yöntemin adı,.
    5. 32 bit tam sayı olarak yazılan java.lang.reflect.Modifier.STATIC yönteminin değiştiricisi.
    6. Yöntemin tanımlayıcısı, () V.
    7. Yöntem adı ve imzasına göre sıralanmış her özel olmayan kurucu için: Yöntemin adı,. 32 bit tam sayı olarak yazılan yöntemin değiştiricileri. Yöntemin tanımlayıcısı.
    8. Yöntem adı ve imzasına göre sıralanmış özel olmayan her yöntem için: Yöntemin adı. 32 bit tam sayı olarak yazılan yöntemin değiştiricileri. Yöntemin tanımlayıcısı.
    9. SHA-1 algoritması, DataOutputStream tarafından üretilen bayt akışı üzerinde yürütülür ve beş adet 32 ​​bit değer üretir [0..4]. Karma değeri, SHA-1 ileti özetinin birinci ve ikinci 32 bit değerlerinden birleştirilir. İleti özeti sonucu, beş adet 32-bit H0 H1 H2 H3 H4 kelimesi sha adında beş int değerin bir dizisindeyse, hash değeri aşağıdaki gibi hesaplanır:
    long hash = ((sha[0] >>> 24) & 0xFF) |
>            ((sha[0] >>> 16) & 0xFF) << 8 |
>            ((sha[0] >>> 8) & 0xFF) << 16 |
>            ((sha[0] >>> 0) & 0xFF) << 24 |
>            ((sha[1] >>> 24) & 0xFF) << 32 |
>            ((sha[1] >>> 16) & 0xFF) << 40 |
>            ((sha[1] >>> 8) & 0xFF) << 48 |
>        ((sha[1] >>> 0) & 0xFF) << 56;

Java'nın serileştirme algoritması

Bir nesneyi serileştirme algoritması aşağıda açıklanmaktadır:
1. Bir örnekle ilişkilendirilen sınıfın meta verilerini yazar.
2. Üst sınıf tanımını java.lang.object bulana kadar özyinelemeli olarak yazar .
3. Meta veri bilgilerini yazmayı tamamladıktan sonra, örnekle ilişkilendirilmiş gerçek verilerle başlar. Ama bu sefer, en üstteki süper sınıftan başlıyor.
4. En az üst sınıftan en türetilmiş sınıfa kadar, örnekle ilişkili verileri özyinelemeli olarak yazar.

Unutmamanız Gereken Şeyler:

  1. Sınıftaki statik alanlar serileştirilemez.

    public class A implements Serializable{
         String s;
         static String staticString = "I won't be serializable";
    }
  2. Serialversionuid okuma sınıfında farklıysa bir InvalidClassExceptionistisna atar .

  3. Bir sınıf serileştirilebilirse, tüm alt sınıfları da serileştirilebilir olacaktır.

    public class A implements Serializable {....};
    
    public class B extends A{...} //also Serializable
  4. Bir sınıfın başka bir sınıfın başvurusu varsa, tüm başvurular Seri hale getirilebilir olmalıdır, aksi takdirde serileştirme işlemi gerçekleştirilmez. Bu durumda, NotSerializableException çalışma zamanında atılır.

Örneğin:

public class B{
     String s,
     A a; // class A needs to be serializable i.e. it must implement Serializable
}

1
'Serileştirme, bir nesnenin durumunun serileştirilmesi işlemidir, bir bayt dizisi şeklinde temsil edilir ve saklanır' anlamsızdır. Eğer serialVersionUIDfarklıysa InvalidClassException, a değil, a atar ClassCastException. serialVersionUIDHesaplamaya saygılı olan tüm bu alanı boşa harcamak gerekmez . Belgeler aşırı uzunlukta alıntılanmış, ancak bağlantılı veya uygun şekilde alıntılanmamıştır. Burada çok fazla tüy ve çok fazla hata var.
Lorne Marquis

'Serileştirme serileştirme sürecidir' anlamsız kalır.
Lorne Marquis

6

Serileştirme, bir nesnenin durumunu bir sabit sürücüye depolanabilmesi için bitlere dönüştürme işlemidir. Aynı nesnenin serileştirmesini kaldırdığınızda, nesnenin durumu daha sonra korunur. Nesnelerin özelliklerini elle kaydetmek zorunda kalmadan nesneleri yeniden oluşturmanıza olanak tanır.

http://en.wikipedia.org/wiki/Serialization


“... böylece sabit diskte saklanabilir.” Veya bir ikili protokol yoluyla aktarılır.
Jim Anderson

4

Java Nesnesi Dizileştirme

resim açıklamasını buraya girin

SerializationJava nesnelerinin grafiğini depolama ( to disk file) veya iletim ( across a network) için bir bayt dizisine dönüştüren bir mekanizmadır , ardından serileştirmeyi kullanarak nesnelerin grafiğini geri yükleyebiliriz. Nesnelerin grafikleri, bir referans paylaşım mekanizması kullanılarak doğru şekilde geri yüklenir. Ancak saklamadan önce, giriş dosyasından / ağından serialVersionUID ve serialVersionUID .class dosyalarının aynı olup olmadığını kontrol edin. Değilse, a java.io.InvalidClassException.

Her sürüm sınıfı, akış yazabildiği ve okuyabileceği orijinal sınıf sürümünü tanımlamalıdır. Örneğin, sürüm sınıfı:

serialVersionUID Sözdizimi

// ANY-ACCESS-MODIFIER static final long serialVersionUID = (64-bit has)L;
private static final long serialVersionUID = 3487495895819393L;

serialVersionUID serileştirme işlemi için gereklidir. Ancak geliştiricinin java kaynak dosyasına eklemesi isteğe bağlıdır. SerialVersionUID dahil değilse, serileştirme çalışma zamanı bir serialVersionUID oluşturur ve sınıfla ilişkilendirir. Serileştirilmiş nesne, bu serialVersionUID öğesini diğer verilerle birlikte içerecektir.

Not - Tüm serileştirilebilir sınıfların açıkça bir serialVersionUID bildirmesi önerilir since the default serialVersionUID computation is highly sensitive to class details that may vary depending on compiler implementationsve bu nedenle serileştirme sırasında beklenmedik serialVersionUID çakışmalarına neden olarak serileştirmenin başarısız olmasına neden olabilir.

Serileştirilebilir Sınıfların İncelenmesi

resim açıklamasını buraya girin


Bir Java nesnesi yalnızca serileştirilebilir. bir sınıf veya üst sınıfı uygular ya varsa java.io.Serializable arayüz veya subinterface, java.io.Externalizable .

  • Bir sınıf , nesnesini başarılı bir şekilde serileştirmek için java.io.Serializable arabirimini uygulamalıdır . Serializable bir işaretleyici arabirimidir ve derleyiciye onu uygulayan sınıfın serileştirilebilir davranış eklenmesi gerektiğini bildirmek için kullanılır. Burada Java Sanal Makinesi (JVM) otomatik serileştirilmesinden sorumludur.

    geçici Anahtar Kelime: java.io.Serializable interface

    Bir nesneyi serileştirirken, nesnenin belirli veri üyelerinin serileştirilmesini istemezsek, geçici değiştiriciyi kullanabiliriz. Geçici anahtar kelime, veri üyesinin seri hale getirilmesini önleyecektir.

    • Geçici veya statik olarak bildirilen alanlar serileştirme işlemi tarafından dikkate alınmaz.

    GEÇİCİ ve VOLATİL

    +--------------+--------+-------------------------------------+
    |  Flag Name   |  Value | Interpretation                      |
    +--------------+--------+-------------------------------------+
    | ACC_VOLATILE | 0x0040 | Declared volatile; cannot be cached.|
    +--------------+--------+-------------------------------------+
    |ACC_TRANSIENT | 0x0080 | Declared transient; not written or  |
    |              |        | read by a persistent object manager.|
    +--------------+--------+-------------------------------------+
    class Employee implements Serializable {
        private static final long serialVersionUID = 2L;
        static int id;
    
        int eno; 
        String name;
        transient String password; // Using transient keyword means its not going to be Serialized.
    }
  • Dışsallaştırılabilir arabirimin uygulanması, nesnenin, nesnenin serileştirilmiş formunun içeriği ve biçimi üzerinde tam kontrol sahibi olmasını sağlar. Externalizable arabiriminin, writeExternal ve readExternal yöntemleri, nesnelerin durumunu kaydetmek ve geri yüklemek için çağrılır. Bir sınıf tarafından uygulandığında, tüm ObjectOutput ve ObjectInput yöntemlerini kullanarak kendi durumlarını yazabilir ve okuyabilirler. Meydana gelen her türlü versiyonlamayı işlemek nesnelerin sorumluluğundadır.

    class Emp implements Externalizable {
        int eno; 
        String name;
        transient String password; // No use of transient, we need to take care of write and read.
    
        @Override
        public void writeExternal(ObjectOutput out) throws IOException {
            out.writeInt(eno);
            out.writeUTF(name);
            //out.writeUTF(password);
        }
        @Override
        public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
            this.eno = in.readInt();
            this.name = in.readUTF();
            //this.password = in.readUTF(); // java.io.EOFException
        }
    }
  • Yalnızca java.io.Serializable veya java.io.Externalizable arabirimini destekleyen nesneler written to/read from akışları olabilir. Serileştirilebilir her nesnenin sınıfı, sınıfın adı ve sınıfın imzası, nesnenin alanlarının ve dizilerinin değerleri ve ilk nesnelerden başvurulan diğer nesnelerin kapatılması dahil olmak üzere kodlanır.

Dosyalar için Serileştirilebilir Örnek

public class SerializationDemo {
    static String fileName = "D:/serializable_file.ser";

    public static void main(String[] args) throws IOException, ClassNotFoundException, InstantiationException, IllegalAccessException {
        Employee emp = new Employee( );
        Employee.id = 1; // Can not Serialize Class data.
        emp.eno = 77;
        emp.name = "Yash";
        emp.password = "confidential";
        objects_WriteRead(emp, fileName);

        Emp e = new Emp( );
        e.eno = 77;
        e.name = "Yash";
        e.password = "confidential";
        objects_WriteRead_External(e, fileName);

        /*String stubHost = "127.0.0.1";
        Integer anyFreePort = 7777;
        socketRead(anyFreePort); //Thread1
        socketWrite(emp, stubHost, anyFreePort); //Thread2*/

    }
    public static void objects_WriteRead( Employee obj, String serFilename ) throws IOException{
        FileOutputStream fos = new FileOutputStream( new File( serFilename ) );
        ObjectOutputStream objectOut = new ObjectOutputStream( fos );
        objectOut.writeObject( obj );
        objectOut.close();
        fos.close();

        System.out.println("Data Stored in to a file");

        try {
            FileInputStream fis = new FileInputStream( new File( serFilename ) );
            ObjectInputStream ois = new ObjectInputStream( fis );
            Object readObject;
            readObject = ois.readObject();
            String calssName = readObject.getClass().getName();
            System.out.println("Restoring Class Name : "+ calssName); // InvalidClassException

            Employee emp = (Employee) readObject;
            System.out.format("Obj[No:%s, Name:%s, Pass:%s]", emp.eno, emp.name, emp.password);

            ois.close();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
    public static void objects_WriteRead_External( Emp obj, String serFilename ) throws IOException {
        FileOutputStream fos = new FileOutputStream(new File( serFilename ));
        ObjectOutputStream objectOut = new ObjectOutputStream( fos );

        obj.writeExternal( objectOut );
        objectOut.flush();

        fos.close();

        System.out.println("Data Stored in to a file");

        try {
            // create a new instance and read the assign the contents from stream.
            Emp emp = new Emp();

            FileInputStream fis = new FileInputStream(new File( serFilename ));
            ObjectInputStream ois = new ObjectInputStream( fis );

            emp.readExternal(ois);

            System.out.format("Obj[No:%s, Name:%s, Pass:%s]", emp.eno, emp.name, emp.password);

            ois.close();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
}

Ağ Üzerinden Serileştirilebilir Örnek

Nesnenin durumunu, aynı bilgisayardaki farklı işlemlerde veya hatta bir ağ üzerinden bağlı birden çok bilgisayarda, ancak veri paylaşarak ve yöntemleri çağırarak birlikte çalışan farklı adres alanlarına dağıtma .

/**
 * Creates a stream socket and connects it to the specified port number on the named host. 
 */
public static void socketWrite(Employee objectToSend, String stubHost, Integer anyFreePort) {
    try { // CLIENT - Stub[marshalling]
        Socket client = new Socket(stubHost, anyFreePort);
        ObjectOutputStream out = new ObjectOutputStream(client.getOutputStream());
        out.writeObject(objectToSend);
        out.flush();
        client.close();
    } catch (IOException e) {
        e.printStackTrace();
    }
}
// Creates a server socket, bound to the specified port. 
public static void socketRead(  Integer anyFreePort ) {
    try { // SERVER - Stub[unmarshalling ]
        ServerSocket serverSocket = new ServerSocket( anyFreePort );
        System.out.println("Server serves on port and waiting for a client to communicate");
            /*System.in.read();
            System.in.read();*/

        Socket socket = serverSocket.accept();
        System.out.println("Client request to communicate on port server accepts it.");

        ObjectInputStream in = new ObjectInputStream(socket.getInputStream());
        Employee objectReceived = (Employee) in.readObject();
        System.out.println("Server Obj : "+ objectReceived.name );

        socket.close();
        serverSocket.close();
    } catch (IOException | ClassNotFoundException e) {
        e.printStackTrace();
    }
}

@görmek


1
Zaten birkaç çok iyi yanıtı olan altı yaşındaki bir soruya bir cevap eklediğinizde, yazım hataları kakofonisinden çok daha iyi yapmanız gerekir.
Lorne Marquis

@ejp Downvoting olumsuz görüşünüzü ifade etme aracıdır. Saldırgan ve sınırda kaba olmak kabul edilemez.
Konstantinos Chertouras

1
@KonstantinosChertouras Downvote için nedenler vermek postere yardımcı olur ve bunlar benim gibi nedenler, sizin gibi ya da değil.
Lorne Marquis

Ayrıca, Serileştirmenin güvenlik amacı olduğunu iddia etmek gibi hatalardan kaçınmanız gerekir. Öyle değil.
Lorne Marquis

@EJP Yazımı güncelledim, Serileştirmenin güvenlik amaçlı olmadığını düzelttim, ancak bir Nesnenin durumunu herhangi bir Depoya dönüştürmek ve SUID kullanarak serileştirme mekanizmasını kullanarak bir nesnenin orijinal durumunu geri almak için kullanılır. JVM to JVM
Yash

3

Serileştirme, bir nesneyi bir depolama ortamına (dosya veya bellek arabelleği gibi) kaydetme veya bir ağ bağlantısı üzerinden ikili biçimde iletme işlemidir. Serileştirilmiş nesneler JVM'den bağımsızdır ve herhangi bir JVM tarafından yeniden serileştirilebilir. Bu durumda "bellekteki" java nesneleri durumu bir bayt akışına dönüştürülür. Bu dosya türü kullanıcı tarafından anlaşılamaz. JVM (Java Sanal Makinesi) tarafından yeniden kullanılan özel bir nesne türüdür. Bir nesneyi serileştirme işlemine aynı zamanda bir nesneyi söndürme veya sıralama denir.

Serileştirilecek nesnenin java.io.SerializableInterface'i uygulaması gerekir . Bir nesne için varsayılan serileştirme mekanizması, nesnenin sınıfını, sınıf imzasını ve geçici olmayan ve statik olmayan tüm alanların değerlerini yazar.

class ObjectOutputStream extends java.io.OutputStream implements ObjectOutput,

ObjectOutputarabirimi arabirimi genişletir ve DataOutputnesneleri serileştirmek ve dosyaya bayt yazmak için yöntemler ekler. ObjectOutputStreamUzanır java.io.OutputStreamve uygular ObjectOutput arabirim. Nesneleri, dizileri ve diğer değerleri bir akışa serileştirir. Böylece kurucusu ObjectOutputStreamşöyle yazılır:

ObjectOutput ObjOut = new ObjectOutputStream(new FileOutputStream(f));

Yukarıdaki kod, bir örneğini parametre olarak ObjectOutputalan ObjectOutputStream( )yapıcı ile sınıfın örneğini oluşturmak için kullanılmıştır FileOuputStream.

ObjectOutputArayüz uygulayarak kullanılır ObjectOutputStreamsınıfı. ObjectOutputStreamNesne seri şekilde imal edilir.

Java'da bir nesnenin serisini kaldırma

Serileştirmenin karşıt işlemine serileştirme denir, yani bir dizi bayttan veri ayıklamak, aynı zamanda şişirme veya dizdirme olarak da adlandırılan serileştirme olarak bilinir.

ObjectInputStream arayüzü genişletir java.io.InputStreamve uygular ObjectInput. Bir giriş akışındaki nesnelerin, dizilerin ve diğer değerlerin serisini kaldırır. Böylece kurucusu ObjectInputStreamşöyle yazılır:

ObjectInputStream obj = new ObjectInputStream(new FileInputStream(f));

Programın yukarıdaki kodu, ObjectInputStreamsınıf tarafından serileştirilmiş olan dosyanın serileştirilmesini kaldırmak için sınıf örneğini oluşturur ObjectInputStream. Yukarıdaki kod FileInputStream, ObjectInputStream()yapıcı giriş akışına ihtiyaç duyduğu için serileştirilmesi gereken belirtilen dosya nesnesini barındıran sınıf örneğini kullanarak örneği oluşturur .



2

Dosyayı Nesne olarak döndürün: http://www.tutorialspoint.com/java/java_serialization.htm

        import java.io.*;

        public class SerializeDemo
        {
           public static void main(String [] args)
           {
              Employee e = new Employee();
              e.name = "Reyan Ali";
              e.address = "Phokka Kuan, Ambehta Peer";
              e.SSN = 11122333;
              e.number = 101;

              try
              {
                 FileOutputStream fileOut =
                 new FileOutputStream("/tmp/employee.ser");
                 ObjectOutputStream out = new ObjectOutputStream(fileOut);
                 out.writeObject(e);
                 out.close();
                 fileOut.close();
                 System.out.printf("Serialized data is saved in /tmp/employee.ser");
              }catch(IOException i)
              {
                  i.printStackTrace();
              }
           }
        }

    import java.io.*;
    public class DeserializeDemo
    {
       public static void main(String [] args)
       {
          Employee e = null;
          try
          {
             FileInputStream fileIn = new FileInputStream("/tmp/employee.ser");
             ObjectInputStream in = new ObjectInputStream(fileIn);
             e = (Employee) in.readObject();
             in.close();
             fileIn.close();
          }catch(IOException i)
          {
             i.printStackTrace();
             return;
          }catch(ClassNotFoundException c)
          {
             System.out.println("Employee class not found");
             c.printStackTrace();
             return;
          }
          System.out.println("Deserialized Employee...");
          System.out.println("Name: " + e.name);
          System.out.println("Address: " + e.address);
          System.out.println("SSN: " + e.SSN);
          System.out.println("Number: " + e.number);
        }
    }

Bu, sorunun 'ne' ya da 'lütfen açıklayın' kısımlarına cevap vermez.
Lorne Marquis

1

| * | Sınıfı serileştirme: Bir nesneyi baytlara ve baytları nesneye geri dönüştürme (Deserialization).

class NamCls implements Serializable
{
    int NumVar;
    String NamVar;
}

| => Nesne Serileştirme, bir nesnenin durumunu bayt buharına dönüştürme işlemidir.

  • | -> Nesnenin JVM ömrünün ötesinde var olmasını istediğinizde uygulayın.
  • | -> Seri Nesne, veritabanında depolanabilir.
  • Serileştirilebilir nesneler insanlar tarafından okunamaz ve anlaşılamaz, böylece güvenliği sağlayabiliriz.

| => Nesne Diziselleştirme, bir nesnenin durumunu alma ve bir nesneye (java.lang.Object) kaydetme işlemidir.

  • Üste Geri Bildirim Ver Durum durumunu saklamadan önce serialVersionUID form giriş dosyası / ağ ve .class dosya serialVersionUID aynı olup olmadığını denetler.
    & nbsp & nbspJava.io.InvalidClassException öğesini atmazsanız.

| => Bir Java nesnesi, yalnızca sınıfı veya üst sınıflarından herhangi biri olduğunda serileştirilebilir

  • java.io.Serializable arabirimini uygular veya
  • alt arayüzü, java.io.

| => Bir sınıftaki statik alanlar serileştirilemez.

class NamCls implements Serializable
{
    int NumVar;
    static String NamVar = "I won't be serializable";;
}

| => Bir sınıfın değişkenini serileştirmek istemiyorsanız, geçici anahtar sözcük kullanın

class NamCls implements Serializable
{
    int NumVar;
    transient String NamVar;
}

| => Bir sınıf serileştirilebilir yaparsa, tüm alt sınıfları serileştirilebilir.

| => Bir sınıfın başka bir sınıfın başvurusu varsa, tüm başvurular Serileştirilebilir olmalıdır, aksi takdirde serileştirme işlemi gerçekleştirilmez. Bu durumda,
NotSerializableException çalışma zamanında atılır.


0

Nesne serileştirmesinin / serileştirmesinin kavramsal amacını / pratikliğini sağlamlaştırmaya potansiyel olarak yardımcı olacak bir benzetme sunacağım .

Bir nesneyi bir fırtına drenajında ​​hareket ettirmeye çalışmak bağlamında nesne serileştirme / serileştirmeyi hayal ediyorum . Nesne, bir ortamdan etkili bir şekilde geçişi sağlamak için , esasen " bu durumda bir dizi bayt " ın daha modüler versiyonlarına "ayrıştırılır" veya serileştirilir . Hesaplamalı bir anlamda, fırtına drenajı boyunca baytların kat ettiği yolu, bir ağda seyahat eden baytlara benzer olarak görebiliriz. Daha arzu edilen bir ulaşım biçimine veya formata uymak için nesnemizi dönüştürüyoruz. Serileştirilmiş nesne tipik olarak daha sonra okunabilen, yazılan veya her ikisinden birden okunabilen bir ikili dosyada saklanır.

Belki de nesnemiz, ayrıştırılmış bir bayt serisi olarak tahliye boyunca kayabildiğinde, nesnenin bu temsilini bir veritabanı veya sabit disk sürücüsünde ikili veri olarak saklamak isteyebiliriz. Ancak ana paket, serileştirme / serileştirme ile, serileştirildikten sonra nesnemizin ikili formda kalmasına izin verme veya serileştirme yaparak nesnenin orijinal biçimini "alma" seçeneğidir.

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.