Javaでのシリアル化の概念は何ですか?



この記事は、Javaでのシリアル化の概念に向けた包括的なアプローチと、理解を深めるためのリアルタイムの例に役立ちます。

のシリアル化 は、オブジェクトをバイトストリームに変換して、Javaオブジェクトを1つのJava仮想マシンから別のJava仮想マシンに転送し、元の形式に再作成することを扱う重要な概念です。この記事のドケットを以下のように並べます。

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

シリアル化 Javaでは、Javaコードを変換するプロセスです。 オブジェクトバイトストリーム 、オブジェクトコードをあるJava仮想マシンから別のマシンに転送し、次のプロセスを使用して再作成します。 デシリアライズ。





Serialization-in-Java-Edureka-Picture-1

なぜシリアル化が必要なのですか Javaで

次の理由でシリアル化が必要です。



  • コミュニケーション :シリアル化にはオブジェクトの手順が含まれます シリアル化 そして 伝染;感染。 これにより、複数のコンピュータシステムでオブジェクトを同時に設計、共有、実行できます。

  • キャッシング :オブジェクトの構築にかかる時間は、オブジェクトの逆シリアル化に必要な時間よりも長くなります。シリアル化により、時間の消費が最小限に抑えられます。 キャッシング 巨大なオブジェクト。

  • ディープコピークローニング シリアル化を使用すると、プロセスが簡単になります。正確な レプリカ オブジェクトのはによって取得されますオブジェクトをにシリアル化する バイト配列 、次にそれを逆シリアル化します。



  • クロス JVM同期: シリアル化の主な利点は、異なる上で実行されている可能性のある異なるJVM間で機能します アーキテクチャ または オペレーティングシステム

  • 永続性: オブジェクトの状態は、シリアル化を適用することで直接保存でき、に保存できます。 データベース それができるように 後で取得。

オブジェクトをシリアル化するにはどうすればよいですか?

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

シリアル化プロセスでは、オブジェクトの状態をバイトストリームに変換して、あるJVMから別のJVMに転送し、バイトストリームを元のオブジェクトに戻すことができるようにします。

//インターフェース

パッケージSerial1import java.io.Serializable public classEmployeeはSerializableを実装します{privatestatic final long serialVersionUID = 1L //シリアルバージョンUIDintid文字列名publicEmployee(int id、String name){this.id = id this.name = name }}

//シリアライズ

パッケージSerial1import java.io. * class Persist {public static void main(String args []){try {Employee emp1 = new Employee(20110、 'John')Employee emp2 = new Employee(22110、 'Jerry')Employee emp3 = new Employee(20120、 'Sam')FileOutputStream fout = new FileOutputStream( 'output.txt')ObjectOutputStream out = new ObjectOutputStream(fout)out.writeObject(emp1)out.writeObject(emp2)out.writeObject(emp3)out。 flush()out.close()System.out.println( 'シリアル化と逆シリアル化が正常に実行されました')} catch(Exception e){System.out.println(e)}}}

出力:

シリアル化と逆シリアル化が正常に実行されました

デシリアライズ :これは、送信側からのオブジェクトのシリアル化されたバイトストリームが受信側で再作成されるシリアル化の逆のプロセスです。

//逆シリアル化

パッケージSerial1import java.io. * class Depersist {public static void main(String args []){try {ObjectInputStream in = new ObjectInputStream(new FileInputStream( 'output.txt'))Employee e1 =(Employee)in.readObject( )従業員e2 =(Employee)in.readObject()従業員e3 =(Employee)in.readObject()System.out.println(e1.id + '' + e1.name)System.out.println(e2.id + '' + e2.name)System.out.println(e3.id + '' + e3.name)in.close()} catch(Exception e){System.out.println(e)}}}

出力:

Pythonで__init__はどういう意味ですか

20110ジョン
22110ジェリー

20120サム

Javaでのシリアル化の長所と短所

利点:

  • シリアル化プロセスは ビルトイン シリアル化を実行するためにサードパーティのソフトウェアを必要としない機能
  • シリアル化手順は次のように証明されています シンプル そして 簡単 理解する

  • シリアル化手順は ユニバーサル さまざまなバックグラウンドを持つ開発者はそれに精通しています

  • 使いやすく、 カスタマイズが簡単

  • シリアル化されたデータストリーム 暗号化、圧縮、認証をサポート そして 安全なJavaコンピューティング

  • 沢山あります 重要なテクノロジー シリアル化に依存しています。

短所:

  • DeSerializationが もろい そして、それらは効果的にDeSerializedされるとは限りません。

  • シリアル化中に宣言された一時変数はメモリスペースを作成しますが、コンストラクターが呼び出されないため、一時変数の初期化が失敗し、 標準Javaフローのバリエーション。

  • シリアル化のプロセスは 非効率的な メモリ使用率の観点から。

  • シリアル化は、必要なアプリケーションで使用するのは好ましくありません 同時アクセス の要件なしで サードパーティのAPI 、シリアル化はすべてのSEごとに遷移制御メカニズムを提供するわけではないため。

  • シリアル化手順が提供されない きめ細かい制御 オブジェクトにアクセスします。

Javaでのシリアル化の実際的な例

継承を使用したシリアル化

ケース– 1:スーパークラスがシリアル化可能である場合、デフォルトでは、そのサブクラスもシリアル化可能です。

この場合、 サブクラス 次の場合、デフォルトでシリアル化可能です スーパークラス を実装しています シリアル化可能なインターフェイス

パッケージSerializationInheritanceimport java.io.FileInputStream import java.io.FileOutputStream import java.io.ObjectInputStream import java.io.ObjectOutputStream import java.io.Serializable class Aimplements Serializable {int i public A(int i){this.i = i}}クラスBはAを拡張します{intj public B(int i、int j){super(i)this.j = j}} public class Test {public static void main(String [] args)throws Exception {B b1 = new B(200,400)System.out.println( 'i =' + b1.i)System.out.println( 'j =' + b1.j)FileOutputStream fos = new FileOutputStream( 'abc.ser')ObjectOutputStream oos = new ObjectOutputStream(fos)oos.writeObject(b1)oos.close()fos.close()System.out.println( 'オブジェクトはシリアル化されました')FileInputStream fis = new FileInputStream( 'abc.ser')ObjectInputStream ois = new ObjectInputStream(fis)B b2 =(B)ois.readObject()ois.close()fis.close()System.out.println( 'オブジェクトは逆シリアル化されました')System.out.println( 'i = '+ b2.i)System.out.println(' j = '+ b2.j)}}

出力:

j = 20
オブジェクトはシリアル化されています
オブジェクトが逆シリアル化されました
i = 200
j = 400

ケース– 2:スーパークラスがSerializable Interfaceを実装していなくても、Serializable Interfaceを実装していれば、サブクラスをシリアル化できます。

この場合、 スーパークラス を実装していません シリアル化可能なインターフェイス 、次に、のオブジェクト サブクラス サブクラスにSerializableInterfaceを実装することにより、手動でシリアル化できます。

パッケージSerializationInheritanceimport java.io.FileInputStream import java.io.FileOutputStream import java.io.ObjectInputStream import java.io.ObjectOutputStream import java.io.Serializable class superclass {int i public superclass(int i){this.i = i} public superclass(){i = 50 System.out.println( 'スーパークラスコンストラクターが呼び出されました')}}クラスサブクラスはスーパークラスを拡張しますSerializable {int j public subclass(int i、int j){super(i)this.j = j }} public class test2 {public static void main(String [] args)throws Exception {subclass b1 = new subclass(10、20)System.out.println( 'i =' + b1.i)System.out.println( 'j =' + b1.j)FileOutputStream fos = new FileOutputStream( 'output.ser')ObjectOutputStream oos = new ObjectOutputStream(fos)oos.writeObject(b1)oos.close()fos.close()System.out.println ( 'オブジェクトはシリアル化されました')FileInputStream fis = new FileInputStream( 'output.ser')ObjectInputStream ois = new ObjectInputStream(fis)subclass b2 =(subclass)ois.readObject( )ois.close()fis.close()System.out.println( 'オブジェクトは逆シリアル化されました')System.out.println( 'i =' + b2.i)System.out.println( 'j =' + b2.j)}}

オブジェクトはシリアル化されています
と呼ばれるスーパークラスコンストラクタ
オブジェクトが逆シリアル化されました
i = 50
j = 20

ケース– 3:スーパークラスはシリアル化可能ですが、サブクラスをシリアル化する必要がない場合。

この場合、サブクラスのシリアル化を防ぐことができますを実装することによって writeObject() そして readObject() サブクラスのメソッドとそれをスローする必要があります NotSerializableException これらの方法から。

パッケージSerializationInheritanceimport java.io.FileInputStream import java.io.FileOutputStream import java.io.IOException import java.io.NotSerializableException import java.io.ObjectInputStream import java.io.ObjectOutputStream import java.io.Serializableclass親はSerializable {intを実装しますi public Parent(int i){this.i = i}}クラスchildextends Parent {int j public child(int i、int j){super(i)this.j = j} private void writeObject(ObjectOutputStream out)throws IOException {throw new NotSerializableException()} private void readObject(ObjectInputStream in)throws IOException {throw new NotSerializableException()}} public class test3 {public static void main(String [] args)throws Exception {child b1 = new child(100、 200)System.out.println( 'i =' + b1.i)System.out.println( 'j =' + b1.j)FileOutputStream fos = new FileOutputStream( 'abc.ser')ObjectOutputStream oos = new ObjectOutputStream( fos)oos.writeObject(b1)oos.close()fos.close()System.out.println( 'Objectシリアル化されました ')FileInputStream fis = new FileInputStream(' abc.ser ')ObjectInputStream ois = new ObjectInputStream(fis)child b2 =(child)ois.readObject()ois.close()fis.close()System.out。 println( 'オブジェクトは逆シリアル化されました')System.out.println( 'i =' + b2.i)System.out.println( 'j =' + b2.j)}}

出力:

Javaでdoubleをintにキャストする

i = 100
j = 200
スレッドの例外 'main' java.io.NotSerializableException
SerializationInheritance.child.writeObject(test3.java:48)で
sun.reflect.NativeMethodAccessorImpl.invoke0(ネイティブメソッド)で

静的メンバーを使用したシリアル化

静的メンバーフィールドのシリアル化は、シリアル化のプロセスでは無視されます。シリアル化はオブジェクトの最新の状態に関連しています。したがって、クラスの特定のインスタンスに関連付けられているデータのみがシリアル化されていますが、静的メンバーフィールドではありません。

package stati importjava.io。*クラスStaticSerialはSerializableを実装します{staticint i = 100 public static void main(String ... ar){StaticSerial ob = new StaticSerial()System.out.println( 'シリアル化時、静的メンバーの値: '+ i)try {FileOutputStream fos = new FileOutputStream(' F:File.ser ')ObjectOutputStream oos = new ObjectOutputStream(fos)oos.writeObject(ob)oos.close()i = 99 FileInputStream fis = new FileInputStream( 'F:File.ser')ObjectInputStream ois = new ObjectInputStream(fis)ob =(StaticSerial)ois.readObject()ois.close()System.out.println( '逆シリアル化後、静的メンバーの値は:' + i)} catch(Exception e){System.out.println(e)}}}

出力:

シリアル化の時点で、静的メンバーの値は100です。
デシリアライズ後、静的メンバーの値は99です。

外部化可能なインターフェイス

ザ・ 外部化可能なインターフェイス Javaのシリアル化に似ていますが、唯一の違いは、提供できることです。 カスタマイズされたシリアル化 ここで、ストリーム内で傷つけるオブジェクトを決定できます。

Externalizableインターフェースはjava.ioで利用可能であり、2つのメソッドを提供します。

  • public void writeExternal(ObjectOutput out)はIOExceptionをスローします
  • public void readExternal(ObjectInput in)はIOExceptionをスローします

SerializationとExternalizeableの主な違いは次のとおりです。

  • 実装 :ユーザーを除く外部化可能なインターフェイス 明示的に シリアル化するオブジェクトについて言及します。シリアル化インターフェイスでは、すべてのオブジェクトと変数がでシリアル化されます ランタイム。

  • メソッド :外部化可能なインターフェイスは、次の2つのメソッドで構成されます。

    • writeExternal()

    • readExternal()

一方、SerializableInterfaceにはメソッドが含まれていません。

  • 処理する: 外部化可能なインターフェイスのシリアル化プロセスは、 カスタマイズ シリアル化プロセスに。ただし、シリアル化インターフェイスは デフォルト シリアル化プロセス。

  • 後方互換性と制御: 外部化可能なインターフェイスは、 バージョン管理 唯一の問題は、スーパークラスのシリアル化中にユーザーが責任を負う必要があることです。一方、シリアル化インターフェイスには、 同じバージョン 両端にJVMがありますが、スーパークラスを含むすべてのオブジェクトとクラスの自動シリアル化が組み込まれています。

  • パブリックNo-Argコンストラクター: 外部化インターフェースのニーズ パブリックNo-Argコンストラクター シリアル化されたオブジェクトを再構築します。シリアル化インターフェイスはNo-Argコンストラクターを必要としませんが、代わりに 反射 シリアル化されたオブジェクトまたはクラスを再構築します。

    Javaのインタプリタとは

package ext import java.io. * class Demoimplements java.io.Serializable {public int a public String b public Demo(int a、String b){this.a = a this.b = b}} class Test {public static void main(String [] args){Demo object = new Demo(1、 'Welcome to Edureka')String filename = 'file.ser' try {FileOutputStream file = new FileOutputStream(filename)ObjectOutputStream out = new ObjectOutputStream(file)out .writeObject(object)out.close()file.close()System.out.println( 'オブジェクトがシリアル化されました')} catch(IOException ex){System.out.println( 'IOExceptionがキャッチされました')}デモobject1 = null tr​​y {FileInputStream file = new FileInputStream(filename)ObjectInputStream in = new ObjectInputStream(file)object1 =(Demo)in.readObject()in.close()file.close()System.out.println( 'Object has beenデシリアライズされた ')System.out.println(' a = '+ object1.a)System.out.println(' b = '+ object1.b)} catch(IOException ex){System.out.println(' IOExceptionがキャッチされました')} catch(ClassNotFoundException ex){System.out .println( 'ClassNotFoundExceptionがキャッチされました')}}}

一時的なキーワード

一時的なキーワードは 予約キーワード Javaで。それはとして使用されます 変数の変更 シリアル化プロセス時。 Transientキーワードを使用して変数を宣言すると、変数がシリアル化されなくなります。

シリアルバージョンUID

シリアル化のプロセスが始まる前に、すべてのシリアル化可能なクラス/オブジェクトは、 一意の識別番号 ホストマシンのJVMによって提供されます。この一意のIDは シリアルバージョンUID 。このUIDは、同じオブジェクトが受信側でDeSerializedされていることを確認するために、受信側のJVMによる識別として使用されます。

Javaでのシリアル化の論争

オラクルの アーキテクトは、Javaからシリアル化を削除する予定です。 1997年の恐ろしい間違い 。慌ただしい調査の結果、Oracleの開発者は、データに脅威を与えるシリアル化手順の設計にいくつかの欠陥があることを発見しました。

1997年、マークラインホールドは述べています–「 シリアル化を「贈り続ける贈り物」と呼びたいのですが、贈り続ける贈り物の種類はセキュリティの脆弱性です。おそらく、Javaのすべての脆弱性の3分の1がシリアル化に関係しており、半分以上になる可能性があります。これは、不安定性は言うまでもなく、驚くほど多くの脆弱性の原因です。」

シリアル化は、Javaの今後のアップデートで削除または置き換えられる可能性がありますが、Javaの初心者の場合、シリアル化は できませんでした 理想的な選択肢になる 彼らのプロジェクトで

Javaでシリアル化を使用する際のベストプラクティス

以下は、従う必要のあるいくつかのベストプラクティスです。

  • 使用をお勧めします javadoc @ シリアル化可能なフィールドを示すためのシリアルタグ。
  • ザ・ 。することが シリアル化されたオブジェクトを表すファイルには、拡張子を使用することをお勧めします。
  • 静的または一時的なフィールドが発生することはお勧めしません デフォルトのシリアル化。
  • 拡張可能なクラス そうでない限り、シリアル化しないでください 必須です。
  • インナークラス シリアル化に関与することは避けてください。

これで、この記事は終わりです。 Javaでのシリアル化の基本、そのタイプ、およびその機能を理解していただければ幸いです。

チェックしてください 25万人以上の満足した学習者のネットワークを持つ信頼できるオンライン学習会社であるEdurekaが世界中に広がっています。 EdurekaのJavaJ2EEおよびSOAトレーニングおよび認定コースは、Java開発者になりたい学生および専門家向けに設計されています。このコースは、Javaプログラミングをすぐに開始できるように設計されており、HibernateやHibernateなどのさまざまなJavaフレームワークに加えて、コアと高度なJavaの両方の概念についてトレーニングします。

質問がありますか?この「Javaでのシリアル化」の記事のコメントセクションで言及してください。できるだけ早くご連絡いたします。