オブジェクトのシリアル化とは何ですか?


回答:


400

シリアル化とは、オブジェクトを一連のバイトに変換することです。これにより、オブジェクトを永続ストレージに簡単に保存したり、通信リンクを介してストリーミングしたりできます。次に、バイトストリームを逆シリアル化できます。元のオブジェクトのレプリカに変換されます。


16
これは義務ですか?送信する前にデータをシリアル化する必要がありますか?どの形式に変換されますか?
フランシスココラレスモラレス

15
@FranciscoCorralesMorales-舞台裏では、すべてのデータがストリーム経由で送信される前にシリアル化されます。どれだけの作業が必要か、どの形式になるかは、使用しているプラ​​ットフォームとライブラリによって異なります。
TarkaDaal 2014

3
@FranciscoCorralesMoralesどう言いますか?プラットフォームとライブラリに依存する形式だと言っているので、本当に形式を知りたいです。
JAVA 2014

1
オブジェクトのみに適用できますか?変数をシリアル化できますか(オブジェクトを使用せずに宣言されています)?
ルマド

@Rumadoオブジェクトのみ
anKotliner

395

シリアライゼーションは、オブジェクトインスタンスを一連のバイトに変換するプロセスと見なすことができます(これはバイナリである場合と、実装に依存しない場合があります)。

たとえば、あるJVMから別のJVMに、ネットワークを介して1つのオブジェクトデータを送信する場合に非常に便利です。

Javaでは、シリアル化メカニズムがプラットフォームに組み込まれていますが、オブジェクトをシリアル化可能にするには、Serializableインターフェースを実装する必要があります。

また、属性を一時的としてマークすることにより、オブジェクト内の一部のデータがシリアル化されないようにすることもできます。

最後に、デフォルトのメカニズムをオーバーライドして、独自のメカニズムを提供できます。これは、いくつかの特別な場合に適しています。これを行うには、javaの非表示機能の 1つを使用します。

シリアル化されるのはオブジェクトの「値」または内容であり、クラス定義ではないことに注意することが重要です。したがって、メソッドはシリアル化されません。

以下は、読みやすくするためのコメント付きの非常に基本的なサンプルです。

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

このプログラムを実行すると、ファイル「o.ser」が作成され、背後で何が起こったかを確認できます。

someIntegerの値を、たとえばInteger.MAX_VALUEに変更すると、出力を比較して違いを確認できます。

その違いを正確に示すスクリーンショットを次に示します。

代替テキスト

違いを見つけられますか?;)

Javaシリアライゼーションには追加の関連フィールドがあります:serialversionUIDですが、これはすでに長すぎてカバーできないと思います。


1
@ raam86 インスタンスは、シリアル化されるオブジェクトです。あなたはメインメソッドでタイプのオブジェクトを作成する別のプログラムと考えるかもしれませんSerializationSample
OscarRyz

2
@ raam86はmainメソッドの最初のステートメントです。SerializationSample instance = new SerializationSample();次に、出力が作成され、オブジェクトがその出力に書き込まれます。
OscarRyz 2012年

1
ああ。十分に近づきませんでした。すごい!!
raam86 2012年

1
@jacktradesやってみませんか?例をコピーして貼り付け、「
NotSerializableException

1
@jacktradesは、オブジェクトのシリアル化が許可されていることをコンピュータに通知されていないためです。:) oosの意味は何ですか。
Chris Bennett

101

6年前の質問に大胆に答え、Javaを初めて使う人に非常に高度な理解を与える

シリアライゼーションとは何ですか?

オブジェクトをバイトに変換する

逆シリアル化とは何ですか?

バイトをオブジェクトに変換し直す(デシリアライゼーション)。

シリアル化はいつ使用されますか?

オブジェクトを永続化する場合。JVMの存続期間を超えてオブジェクトを存在させたい場合。

実際の例:

ATM:口座名義人がATMを介してサーバーからお金を引き出そうとすると、引き出しの詳細などの口座名義人の情報がシリアル化され、サーバーに送信されます。

Javaでのシリアライゼーションの実行方法。

  1. 実装java.io.Serializableインターフェイス(実装するメソッドがないマーカーインターフェイス)。

  2. オブジェクトを永続化する:java.io.ObjectOutputStreamクラス、つまり下位レベルのバイトストリームのラッパーであるフィルターストリームを使用します(オブジェクトをファイルシステムに書き込むか、フラット化されたオブジェクトをネットワークワイヤーを介して転送し、反対側で再構築します)。

    • writeObject(<<instance>>) -オブジェクトを書き込む
    • readObject() -シリアル化されたオブジェクトを読み取る

覚えておいてください:

オブジェクトをシリアル化すると、オブジェクトのクラスファイルやメソッドではなく、オブジェクトの状態のみが保存されます。

2バイトのオブジェクトをシリアル化すると、51バイトのシリアル化されたファイルが表示されます。

オブジェクトがシリアル化および非シリアル化される方法をステップします。

回答:どのようにして51バイトのファイルに変換しましたか?

  • 最初に、シリアル化ストリームのマジックデータを書き込みます(STREAM_MAGIC = "AC ED"およびSTREAM_VERSION = JVMのバージョン)。
  • 次に、インスタンスに関連付けられたクラスのメタデータ(クラスの長さ、クラスの名前、serialVersionUID)を書き込みます。
  • 次に、スーパークラスのメタデータが見つかるまで再帰的に書き込みますjava.lang.Object
  • 次に、インスタンスに関連付けられた実際のデータから始めます。
  • 最後に、インスタンスに関連付けられているオブジェクトのデータをメタデータから実際のコンテンツに書き込みます。

Javaシリアライゼーションの詳細については、こちらのリンクをご覧ください。

編集:もう1つ読みやすいリンク

これはいくつかのよくある質問に答えます:

  1. クラス内のフィールドをシリアル化しない方法。
    回答:一時的なキーワードを使用する

  2. 子クラスがシリアル化されると、親クラスはシリアル化されますか?
    回答:いいえ、親がSerializableインターフェースの親フィールドを拡張していない場合は、シリアル化されません。

  3. 親がシリアル化されると、子クラスはシリアル化されますか?
    回答:はい、デフォルトで子クラスもシリアル化されます。

  4. 子クラスがシリアル化されないようにするにはどうすればよいですか?
    回答:a。writeObjectおよびreadObjectメソッドをオーバーライドして、をスローしNotSerializableExceptionます。

    b。また、すべてのフィールドを子クラスで一時的にマークすることもできます。

  5. Thread、OutputStreamとそのサブクラス、Socketなどの一部のシステムレベルのクラスはシリアル化できません。

3
この簡潔な答えを本当にありがとう、それはとても役に立ちました!
Nobi、

21

シリアライゼーションは、メモリ内の「ライブ」オブジェクトを取得し、それをどこかに(たとえば、メモリ、ディスク上の)保存できるフォーマットに変換し、後で「デシリアライズ」してライブオブジェクトに戻します。


14

@OscarRyzの表示方法が気に入りました。ここで私はもともと@amitguptaによって書かれた連載話を続けていますが。

ロボットのクラス構造について知り、データをシリアル化したとしても、地球の科学者はロボットを機能させるためにデータを逆シリアル化できませんでした。

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

火星の科学者たちは完全な支払いを待っていました。支払いが完了すると、火星の科学者はシリアルバージョンUIDを地球の科学者と共有しました。地球の科学者はそれをロボットのクラスに設定し、すべてがうまくなりました。


9

シリアライゼーションとは、Javaでオブジェクトを永続化することです。オブジェクトの状態を保存し、後で状態を再構築する場合(別のJVMにある可能性があります)、シリアライゼーションを使用できます。

オブジェクトのプロパティは保存されるだけであることに注意してください。オブジェクトを再び復活させる場合は、メンバー変数のみが格納され、メンバー関数は格納されないため、クラスファイルが必要です。

例えば:

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

Searializableは、クラスがシリアル化可能であることを示すマーカーインターフェイスです。マーカーインターフェイスは、それが単なる空のインターフェイスであることを意味し、そのインターフェイスを使用すると、このクラスをシリアル化できることをJVMに通知します。


9

私自身のブログの2セント:

ここにシリアライゼーションの詳細な説明があります:(私のブログ)

シリアル化:

シリアル化は、オブジェクトの状態を永続化するプロセスです。それは一連のバイトの形で表され、保存されます。これはファイルに保存できます。ファイルからオブジェクトの状態を読み取って復元するプロセスは、逆シリアル化と呼ばれます。

シリアル化の必要性は何ですか?

現代のアーキテクチャでは、常にオブジェクトの状態を保存して取得する必要があります。たとえばHibernateでは、オブジェクトを格納するには、クラスをSerializableにする必要があります。これは、オブジェクトの状態がバイトの形式で保存されると、別のシステムに転送され、その状態から読み取ってクラスを取得できるということです。オブジェクトの状態は、データベース、別のjvm、または別のコンポーネントから取得できます。シリアル化の助けを借りて、オブジェクトの状態を取得できます。

コード例と説明:

まず、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;
        }
}

上記のコードでは、ItemクラスがSerializableを実装していることがわかります。

これは、クラスをシリアル化できるようにするインターフェイスです。

これで、serialVersionUIDという変数がLong変数に初期化されていることがわかります。この数は、クラスの状態とクラス属性に基づいてコンパイラーによって計算されます。これは、jvmがファイルからオブジェクトの状態を読み取るときに、オブジェクトの状態を識別するのに役立つ番号です。

そのために、オラクルの公式ドキュメントを見ることができます。

シリアル化ランタイムは、シリアル化可能な各クラスに、serialVersionUIDと呼ばれるバージョン番号を関連付けます。これは、シリアル化に関して、シリアル化されたオブジェクトの送信者と受信者が、そのオブジェクトに対して、シリアル化に関して互換性のあるクラスを読み込んだことを確認するために使用されます。レシーバーが、対応するセンダーのクラスとは異なるserialVersionUIDを持つオブジェクトのクラスをロードした場合、デシリアライズはInvalidClassExceptionになります。シリアライズ可能なクラスは、「serialVersionUID」という名前のフィールドを宣言することにより、それ自体のシリアルバージョンUIDを明示的に宣言できます。シリアル化可能なクラスがserialVersionUIDを明示的に宣言していない場合、次に、直列化ランタイムは、Java(TM)オブジェクト直列化仕様で説明されているように、クラスのさまざまな側面に基づいて、そのクラスのデフォルトのserialVersionUID値を計算します。ただし、デフォルトのserialVersionUIDの計算は、コンパイラーの実装によって異なる可能性があるクラスの詳細に非常に敏感であり、その結果、逆シリアル化中に予期しないInvalidClassExceptionsが発生する可能性があるため、すべてのシリアル化可能なクラスで明示的にserialVersionUID値を宣言することを強くお勧めします。したがって、さまざまなJavaコンパイラーの実装間で一貫したserialVersionUID値を保証するには、シリアライズ可能なクラスで明示的なserialVersionUID値を宣言する必要があります。また、明示的なserialVersionUID宣言では、可能な場合はプライベート修飾子を使用することを強くお勧めします。

あなたが気づいたら、私たちが使用した別のキーワードが一時的です。

フィールドが直列化可能でない場合は、一時的としてマークする必要があります。ここでは、itemCostPriceを一時的としてマークし、ファイルに書き込まないようにします。

次に、オブジェクトの状態をファイルに書き込んで、そこから読み取る方法を見てみましょう。

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

上記では、オブジェクトのシリアライズとデシリアライズの例を見ることができます。

そのために2つのクラスを使用しました。オブジェクトをシリアル化するために、ObjectOutputStreamを使用しました。メソッドwriteObjectを使用して、ファイルにオブジェクトを書き込みました。

逆シリアル化では、ファイルからオブジェクトを読み取るObjectInputStreamを使用しました。readObjectを使用して、ファイルからオブジェクトデータを読み取ります。

上記のコードの出力は次のようになります。

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]

逆シリアル化されたオブジェクトのitemCostPriceは、書き込まれていないためnullであることに注意してください

この記事のパートIでは、Javaシリアライゼーションの基本についてすでに説明しました。

それでは、それについて深く議論し、それがどのように機能するかを説明しましょう。

まず、serialversionuidから始めましょう

serialVersionUIDのは、直列化可能クラスのバージョンコントロールとして使用されています。

serialVersionUIDを明示的に宣言しない場合、JVMはSerializableクラスのさまざまなプロパティに基づいて自動的にそれを行います。

serialversionuidを計算するJavaのアルゴリズム(詳細はこちら)

  1. クラス名。
    1. 32ビット整数として記述されたクラス修飾子。
    2. 名前でソートされた各インターフェースの名前。
    3. フィールド名でソートされたクラスの各フィールド(プライベート静的フィールドとプライベート一時フィールドを除く:フィールドの名前。32ビット整数として書き込まれたフィールドの修飾子。フィールドの記述子。
    4. クラス初期化子が存在する場合は、次のように書きます:メソッドの名前。
    5. メソッドの修飾子であるjava.lang.reflect.Modifier.STATIC。32ビット整数として記述されます。
    6. メソッドの記述子、()V。
    7. メソッド名とシグニチャーでソートされた各非プライベートコンストラクターの場合:メソッドの名前。32ビット整数として記述されたメソッドの修飾子。メソッドの記述子。
    8. メソッド名とシグニチャーでソートされた非プライベートメソッドごと:メソッドの名前。32ビット整数として記述されたメソッドの修飾子。メソッドの記述子。
    9. SHA-1アルゴリズムは、DataOutputStreamによって生成されたバイトのストリームで実行され、5つの32ビット値sha [0..4]を生成します。ハッシュ値は、SHA-1メッセージダイジェストの最初と2番目の32ビット値から組み立てられます。メッセージダイジェストの結果である5つの32ビットワードH0 H1 H2 H3 H4が、shaという名前の5つのint値の配列にある場合、ハッシュ値は次のように計算されます。
    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のシリアル化アルゴリズム

オブジェクトをシリアル化するアルゴリズムは次のとおりです
。1.インスタンスに関連付けられたクラスのメタデータを書き出します。
2. java.lang.objectが見つかるまで、スーパークラスの説明を再帰的に書き出します
3.メタデータ情報の書き込みが完了すると、インスタンスに関連付けられている実際のデータから開始されます。しかし、今回は最上位のスーパークラスから始まります。
4.インスタンスに関連付けられたデータを、最小のスーパークラスから最大の派生クラスまで、再帰的に書き込みます。

心に留めておくべきこと:

  1. クラスの静的フィールドはシリアル化できません。

    public class A implements Serializable{
         String s;
         static String staticString = "I won't be serializable";
    }
  2. serialversionuidが読み取りクラスで異なる場合は、InvalidClassException例外がスローされます。

  3. クラスが直列化可能を実装している場合、そのすべてのサブクラスも直列化可能です。

    public class A implements Serializable {....};
    
    public class B extends A{...} //also Serializable
  4. クラスに別のクラスの参照がある場合、すべての参照はSerializableである必要があります。そうしないと、シリアル化プロセスは実行されません。そのような場合、実行時にNotSerializableExceptionがスローされます。

例えば:

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

1
「シリアライゼーションは、オブジェクトの状態をシリアライズするプロセスであり、バイトのシーケンスの形式で表され、格納されます」は意味がありません。serialVersionUIDが異なる場合は、InvalidClassExceptionではなくをスローしClassCastExceptionます。serialVersionUID計算を再指定するスペースをすべて無駄にする必要はありません。ドキュメンテーションは引用されていますが、長すぎますが、リンクも引用もされていません。ここでは綿毛が多すぎ、エラーが多すぎます。
ローン侯爵

「シリアライズはシリアライズのプロセスです」というのは意味がありません。
ローン侯爵

6

シリアル化とは、オブジェクトの状態をビットに変換して、ハードドライブに保存できるようにするプロセスです。同じオブジェクトを逆シリアル化すると、後でその状態が保持されます。オブジェクトのプロパティを手動で保存せずにオブジェクトを再作成できます。

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


「ハードドライブに保存できるように」または、バイナリプロトコルを介して転送されます。
ジムアンダーソン、

4

Java オブジェクトのシリアル化

ここに画像の説明を入力してください

SerializationJavaオブジェクトのグラフをstorage(to disk file)またはtransmission(across a network)のバイト配列に変換するメカニズムです。逆シリアル化を使用することで、オブジェクトのグラフを復元できます。オブジェクトのグラフは、参照共有メカニズムを使用して正しく復元されます。ただし、保存する前に、input-file / networkのserialVersionUIDと.classファイルのserialVersionUIDが同じかどうかを確認してください。そうでない場合は、をスローしjava.io.InvalidClassExceptionます。

バージョン管理された各クラスは、ストリームの書き込みと読み取りが可能な元のクラスバージョンを識別する必要があります。たとえば、バージョン管理されたクラスは、以下を宣言する必要があります。

serialVersionUID構文

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

serialVersionUIDは、シリアル化プロセスに不可欠です。ただし、開発者がJavaソースファイルに追加するかどうかは任意です。serialVersionUIDが含まれていない場合、シリアル化ランタイムはserialVersionUIDを生成し、それをクラスに関連付けます。シリアル化されたオブジェクトには、このserialVersionUIDが他のデータと共に含まれます。

-すべての直列化可能クラスは、serialVersionUIDを明示的に宣言することを強くお勧めしsince the default serialVersionUID computation is highly sensitive to class details that may vary depending on compiler implementationsます。これにより、逆シリアル化中に予期しないserialVersionUIDの競合が発生し、逆シリアル化が失敗する可能性があります。

シリアライズ可能なクラスの検査

ここに画像の説明を入力してください


Javaオブジェクトはシリアル化のみ可能です。クラスまたはそのスーパークラスの実装のいずれかのいずれかの場合にjava.io.Serializableインタフェースまたはそのサブインターフェイス、java.io.Externalizable

  • オブジェクトを正常にシリアル化するには、クラスがjava.io.Serializableインターフェースを実装する必要があります。Serializableはマーカーインターフェイスであり、それを実装するクラスにシリアライズ可能な動作を追加する必要があることをコンパイラに通知するために使用されます。ここでは、Java仮想マシン(JVM)が自動シリアル化を担当します。

    一時的なキーワード: java.io.Serializable interface

    オブジェクトのシリアル化中に、オブジェクトの特定のデータメンバーをシリアル化したくない場合は、transient修飾子を使用できます。一時的なキーワードは、そのデータメンバーがシリアル化されるのを防ぎます。

    • 一時的または静的として宣言されたフィールドは、シリアル化プロセスによって無視されます。

    トランジェントボラタイル

    +--------------+--------+-------------------------------------+
    |  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.
    }
  • Externalizableインターフェースを実装すると、オブジェクトは、オブジェクトの直列化された形式の内容と形式を完全に制御できるようになります。オブジェクトの状態を保存および復元するために、ExternalizableインターフェイスのメソッドであるwriteExternalおよびreadExternalが呼び出されます。クラスによって実装されると、ObjectOutputおよびObjectInputのすべてのメソッドを使用して、独自の状態を書き込みおよび読み取ることができます。発生するバージョン管理を処理するのはオブジェクトの責任です。

    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
        }
    }
  • のみのは、java.io.Serializableインターフェースかjava.io.Externalizableインターフェースをサポートすることができるオブジェクトwritten to/read fromストリーム。各直列化可能オブジェクトのクラスは、クラスのクラス名とシグネチャ、オブジェクトのフィールドと配列の値、および初期オブジェクトから参照される他のオブジェクトのクロージャを含めてエンコードされます。

ファイルのシリアライズ可能な例

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

ネットワークを介したシリアライズ可能な例

オブジェクトの状態を、同じコンピューター上の異なるプロセス、またはネットワーク経由で接続された複数のコンピューターでさえ、異なるアドレス空間に分散しますが、データを共有し、メソッドを呼び出すことによって連携します。

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

@見る


1
すでにいくつかの非常に優れた回答がある6年前の質問に回答を追加するときは、つづりの間違いの不協和音よりもはるかに優れている必要があります。
ローン侯爵2015

@ejpダウン投票はあなたの否定的な意見を表明するためのツールです。攻撃的で境界線の失礼な態度は容認できません。
Konstantinos Chertouras 16

1
@KonstantinosChertouras反対投票の理由を説明することはポスターに役立ちます。それらは、あなたがそうであるかどうかにかかわらず、私の理由です。
ローン侯爵

また、シリアライゼーションにはセキュリティ上の目的があると主張するなどのエラーを回避する必要もあります。そうではありません。
ローン侯爵

@EJP投稿を更新しましたが、シリアライゼーションはセキュリティ上の目的ではないことを修正しましたが、オブジェクトの状態を任意のストレージに変換し、逆シリアル化メカニズムを通じてSUIDを使用してオブジェクトの元の状態を取得するために使用されます。JVM to JVM
Yash

3

シリアル化とは、オブジェクトを記憶媒体(ファイルやメモリバッファーなど)に保存するプロセス、またはネットワーク接続を介してバイナリ形式でオブジェクトを送信するプロセスです。シリアル化されたオブジェクトはJVMに依存せず、どのJVMでも再シリアル化できます。この場合、「メモリ内」のJavaオブジェクトの状態はバイトストリームに変換されます。このタイプのファイルはユーザーが理解できません。これは特別なタイプのオブジェクトです。つまり、JVM(Java仮想マシン)によって再利用されます。オブジェクトをシリアル化するこのプロセスは、オブジェクトのデフレートまたはマーシャリングとも呼ばれます。

シリアル化されるオブジェクトは、java.io.Serializableインターフェイスを実装する必要があります。オブジェクトのデフォルトのシリアル化メカニズムは、オブジェクトのクラス、クラスシグネチャ、およびすべての非一時フィールドと非静的フィールドの値を書き込みます。

class ObjectOutputStream extends java.io.OutputStream implements ObjectOutput,

ObjectOutputinterfaceは、DataOutputインターフェイスを拡張し、オブジェクトをシリアル化してファイルにバイトを書き込むためのメソッドを追加します。ObjectOutputStream拡張java.io.OutputStreamや実装がObjectOutput インタフェース。オブジェクト、配列、およびその他の値をストリームにシリアル化します。したがって、のコンストラクタは次のように ObjectOutputStream記述されます。

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

上記のコードは、のインスタンスをパラメーターとして取るコンストラクターを使用して、ObjectOutputクラスのインスタンスを作成するために使用されています。ObjectOutputStream( )FileOuputStream

ObjectOutputインタフェースは、実装によって使用されるObjectOutputStreamクラスを。ObjectOutputStreamオブジェクトをシリアル化するように構成されています。

Javaでのオブジェクトの逆シリアル化

シリアライゼーションの反対の操作はデシリアライゼーションと呼ばれます。つまり、一連のバイトからデータを抽出することは、デシリアライゼーションと呼ばれ、インフレートまたはアンマーシャリングとも呼ばれます。

ObjectInputStream インターフェースを拡張java.io.InputStreamして実装しObjectInputます。入力ストリームからオブジェクト、配列、およびその他の値を逆シリアル化します。したがって、のコンストラクタは次のように ObjectInputStream記述されます。

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

上記のプログラムのコードは、ObjectInputStreamクラスによってシリアル化されたファイルを逆シリアル化するクラスのインスタンスを作成しますObjectInputStream。上記のコードはFileInputStreamObjectInputStream()コンストラクターが入力ストリームを必要とするため、逆シリアル化する必要がある指定されたファイルオブジェクトを保持するクラスのインスタンスを使用してインスタンスを作成します。


2

シリアライゼーションとは、Javaオブジェクトをバイト配列に変換し、その状態を保持したまま再びオブジェクトに戻すプロセスです。ネットワーク経由でオブジェクトを送信したり、ディスクにキャッシュしたりするなど、さまざまな用途に役立ちます。

プロセスのプログラミング部分を非常によく説明しているこの短い記事を読んでから、Serializable javadocに進んでください。この関連する質問を読むことにも興味があるかもしれません。


2

ファイルをオブジェクトとして返す: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);
        }
    }

これは、質問の「内容」や「説明してください」の部分には答えません。
ローンの侯爵

1

| * | クラスのシリアライズ:オブジェクトをバイトに変換し、バイトをオブジェクトに戻します(デシリアライゼーション)。

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

| =>オブジェクトのシリアル化は、オブジェクトの状態をバイトのストリームに変換するプロセスです。

  • |->オブジェクトをJVMの存続期間を超えて存在させたい場合に実装します。
  • |->シリアル化されたオブジェクトはデータベースに保存できます。
  • |-> Serializable-objectsは人間が読み取って理解することができないため、セキュリティを確保できます。

| =>オブジェクトのデシリアライゼーションは、オブジェクトの状態を取得してオブジェクト(java.lang.Object)に格納するプロセスです。

  • |->状態を保存する前に、serialVersionUIDフォームinput-file / networkと.classファイルserialVersionUIDが同じかどうかをチェックします。
    &nbsp&nbspスローされない場合、java.io.InvalidClassException。

| => Javaオブジェクトは、そのクラスまたはそのスーパークラスのいずれかである場合にのみシリアライズ可能です

  • java.io.Serializableインターフェースまたは
  • そのサブインターフェース、java.io.Externalizable。

| =>クラスの静的フィールドはシリアル化できません。

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

| =>クラスの変数をシリアル化したくない場合は、transientキーワードを使用します

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

| =>クラスが直列化可能を実装する場合、そのすべてのサブクラスも直列化可能になります。

| =>クラスに別のクラスの参照がある場合、すべての参照はSerializableである必要があります。そうでない場合、シリアル化プロセスは実行されません。そのような場合、
実行時にNotSerializableExceptionがスローされます。


0

オブジェクトのシリアライゼーション/デシリアライゼーションの概念的な目的/実用性を固めるのに役立つ可能性のある類推を提供します。

ストームドレインを介してオブジェクトを移動しようとする状況で、オブジェクトのシリアル化/逆シリアル化を想像します。媒体の通過を効果的に許可するために、オブジェクトは本質的に「分解」またはそれ自体のよりモジュール化れたバージョン(この場合は一連のバイト)にシリアルれます。計算上の意味で、ストームドレインを介してバイトが移動するパスは、ネットワークを移動するバイトに似ていると考えることができます。より望ましい輸送モードまたはフォーマットに準拠するために、オブジェクトを変換しています。シリアル化されたオブジェクトは通常、後で読み取る、書き込む、またはその両方を実行できるバイナリファイルに格納されます。

おそらく、オブジェクトが分解された一連のバイトとしてドレインをすり抜けることができたら、オブジェクトのその表現をバイナリデータとしてデータベースまたはハードディスクドライブに格納することができます。ただし、主なポイントは、シリアル化/逆シリアル化では、オブジェクトをシリアル化した後もバイナリ形式のままにするか、逆シリアル化を実行してオブジェクトの元の形式を「取得」するオプションがあることです。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.