Java のシリアル化と逆シリアル化とは何ですか? Javaのシリアライズとデシリアライズの実装方法

不言
リリース: 2018-10-13 14:55:57
転載
3317 人が閲覧しました

この記事では、Java のシリアル化と逆シリアル化とは何ですか? Java のシリアル化と逆シリアル化の実装方法は参考になると思います。

シリアライゼーションとデシリアライゼーションは Java の比較的基本的な知識ポイントですが、Java がそれをどのように実装しているのかを深く掘り下げて尋ねると、多くの人は数文しか理解できない、または理解できないと思います。シリアル化と逆シリアル化は圧倒的かもしれません。シリアル化とは何か、シリアル化解除とは何か、それがどのようなシナリオで使用されるのかなど、どう説明すればよいのかわかりません。面接官はこう言いました。「基礎となるシリアル化と逆シリアル化がどのように実装されているか知っていますか?」シリアル化と逆シリアル化についていくつか説明しましょう。

まず第一に、シリアル化と逆シリアル化とは何かという概念的なことを明確にする必要があります。

Java は Java オブジェクトをバイト シーケンスに変換するプロセスであり、Java 逆シリアル化はそのプロセスを指します。一連のバイトを Java オブジェクトに復元する方法。

シリアル化: オブジェクトのシリアル化の主な機能は、オブジェクトの転送および保存時にオブジェクトの整合性と配信可能性を保証することです。シリアル化とは、オブジェクトを順序付けされたバイト ストリームに変換して、ネットワーク上で送信したり、ローカル ファイルに保存したりすることです。シリアル化されたバイト ストリームは、Java オブジェクトのステータスと関連する説明情報を保存します。シリアル化メカニズムの中核となる機能は、オブジェクトの状態の保存と再構築です。

デシリアライズ: クライアントは、ファイルまたはネットワークからシリアル化されたオブジェクトのバイト ストリームを取得した後、バイト ストリームに保存されているオブジェクトのステータスと説明情報に基づいて、デシリアライズを通じてオブジェクトを再構築します。

本質的に、シリアル化はエンティティ オブジェクトの状態を特定の形式で順序付けされたバイト ストリームに書き込むことであり、逆シリアル化は順序付けされたバイト ストリームからオブジェクトを再構築し、オブジェクトの状態を復元することです。これは、ファイルの圧縮と解凍の概念に似ています。

シリアル化と逆シリアル化が必要な理由:

プロセスがリモートで通信する場合、テキスト、画像、オーディオ、ビデオなどのさまざまな種類のデータを相互に送信できることがわかっています。 . であり、これらのデータはバイナリ シーケンスの形式でネットワーク上に送信されます。

では、2 つの Java プロセスが通信するとき、プロセス間でのオブジェクトの転送は実現できるのでしょうか?答えは「はい」です。では、どうすればよいでしょうか?これには Java のシリアル化と逆シリアル化が必要です。

言い換えると、送信者はこの Java オブジェクトをバイト シーケンスに変換してネットワーク上に送信する必要があり、一方、受信者は Java オブジェクトをデータから復元する必要があります。セクションのシーケンス。

なぜ Java シリアル化と逆シリアル化が必要なのかを理解した後は、当然 Java シリアル化の利点について考えることになります。

まず、データの永続化が実現され、シリアル化によってデータをハードディスクに永続的に保存できます (通常はファイルに保存されます)。

2 つ目は、シリアル化を使用してリモート通信を実現することです。つまり、オブジェクトのバイト シーケンスをネットワーク上に送信します。

一般に、これは次の点のように要約できます。

(1) オブジェクトを永続的に保存し、オブジェクトのバイト シーケンスをローカル ファイルまたはデータベースに保存します。 2) オブジェクトはシリアル化を通じてバイト ストリームの形式でネットワーク内で送受信されます。
(3) オブジェクトはシリアル化を通じてプロセス間で転送されます。

シリアル化アルゴリズムは通常、次のことを段階的に実行します。

(1) オブジェクトインスタンスに関するクラスメタデータを出力します。

(2) スーパークラスがなくなるまで、クラスのスーパークラス記述を再帰的に出力します。
(3) クラスのメタデータが完成したら、最上位のスーパークラスからオブジェクトインスタンスの実データ値の出力を開始します。
(4) インスタンスデータを上から下へ再帰的に出力する

では、Java でシリアル化と逆シリアル化を実装するにはどうすればよいでしょうか?

1: JDK クラス ライブラリのシリアル化および逆シリアル化 API

(1) java.io.ObjectOutputStream: オブジェクト出力ストリームを表します。

その writeObject(Object obj) メソッド。パラメータで指定された obj オブジェクトをシリアル化し、取得したバイト シーケンスをターゲットの出力ストリームに書き込むことができます。

(2) java.io.ObjectInputStream: オブジェクトの入力ストリームを表します。 () メソッドは、ソース入力ストリームからバイト シーケンスを読み取り、それらをオブジェクトに逆シリアル化して、それを返します。シリアル化することはできますが、そうでない場合は例外がスローされます。

3: Java オブジェクトのシリアル化と逆シリアル化を実装するメソッド

User クラスとそのオブジェクトをシリアル化する必要があると仮定します。次の 3 つのメソッドがあります。

(1 ) User クラスが Serializable インターフェイスのみを実装している場合は、次の方法でシリアル化および逆シリアル化できます。

ObjectOutputStream は、デフォルトのシリアル化メソッドを使用して、User オブジェクトの非一時的なインスタンス変数をシリアル化します。

ObjcetInputStream は、デフォルトの逆シリアル化メソッドを使用して、User オブジェクトの非一時的なインスタンス変数を逆シリアル化します。

(2) User クラスが Serializable インターフェイスのみを実装し、readObject(ObjectInputStream in) および writeObject(ObjectOutputSteam out) も定義している場合、次のメソッドがシリアル化と逆シリアル化に使用されます。

ObjectOutputStream调用User对象的writeObject(ObjectOutputStream out)的方法进行序列化。 
ObjectInputStream会调用User对象的readObject(ObjectInputStream in)的方法进行反序列化。

(3)若User类实现了Externalnalizable接口,且User类必须实现readExternal(ObjectInput in)和writeExternal(ObjectOutput out)方法,则按照以下方式进行序列化与反序列化。

ObjectOutputStream调用User对象的writeExternal(ObjectOutput out))的方法进行序列化。 
ObjectInputStream会调用User对象的readExternal(ObjectInput in)的方法进行反序列化。

四 :JDK类库中序列化的步骤

1  . 创建一个对象输出流,可以包装一个其它类型的目标输出流,如文件输出流:

ObjectOutputStream os = new ObjectOutputStream(new FileOutputStream("D:\\os.out"));
ログイン後にコピー

2 . 通过对象输出流的writeObject()方法写对象:

os.writeObject(new User("zhangsan", "123456", "male"));
ログイン後にコピー

五 : JDK类库中反序列化的步骤

1 . 创建一个对象输入流,它可以包装一个其它类型输入流,如文件输入流:

ObjectInputStream ois= new ObjectInputStream(new FileInputStream("object.out"));
ログイン後にコピー

2 .通过对象输出流的readObject()方法读取对象:

User user = (User) ois.readObject();
ログイン後にコピー

为保证正确读取数据,完成反序列化,必须保证向对象输出流写对象的顺序与从对象输入流中读对象的顺序一致。

举个栗子:

public class SerialDemo {
    public static void main(String[] args) throws IOException, ClassNotFoundException {
        //序列化
        FileOutputStream outputos = new FileOutputStream("object.out");
        ObjectOutputStream oos = new ObjectOutputStream(outputos );
        User user1 = new User("zhangsan", "123456", "male");
        oos.writeObject(user1);
        oos.flush();
        oos.close();
        //反序列化
        FileInputStream inputos= new FileInputStream("object.out");
        ObjectInputStream ois = new ObjectInputStream(inputos);
        User user2 = (User) ois.readObject();
        System.out.println(user2.getUserName()+ " " + 
            user2.getPassword() + " " + user2.getSex());
        //反序列化的输出结果为:zhangsan123456 male
    }
}

public class User implements Serializable {
    private String userName;
    private String password;
    private String sex;
    //全参构造方法、get和set方法
}
ログイン後にコピー

  

相关的注意事项:

1、序列化时,只对对象的状态进行保存,而不管对象的方法;

2、当一个父类实现序列化,子类自动实现序列化,不需要显式实现Serializable接口;

3、当一个对象的实例变量引用其他对象,序列化该对象时也把引用对象进行序列化;

4、并非所有的对象都可以序列化,至于为什么不可以,有很多原因了,比如:

安全方面的原因,比如一个对象拥有private,public等field,对于一个要传输的对象,比如写到文件,或者进行RMI传输等等,在序列化进行传输的过程中,这个对象的private等域是不受保护的;

资源分配方面的原因,比如socket,thread类,如果可以序列化,进行传输或者保存,也无法对他们进行重新的资源分配,而且,也是没有必要这样实现;

5、声明为static和transient类型的成员数据不能被序列化。因为static代表类的状态,transient代表对象的临时数据。

6、序列化运行时使用一个称为 serialVersionUID 的版本号与每个可序列化类相关联,该序列号在反序列化过程中用于验证序列化对象的发送者和接收者是否为该对象加载了与序列化兼容的类。为它赋予明确的值。显式地定义serialVersionUID有两种用途:

在某些场合,希望类的不同版本对序列化兼容,因此需要确保类的不同版本具有相同的serialVersionUID;

在某些场合,不希望类的不同版本对序列化兼容,因此需要确保类的不同版本具有不同的serialVersionUID。

7、Java有很多基础类已经实现了serializable接口,比如String,Vector等。但是也有一些没有实现serializable接口的;

8、如果一个对象的成员变量是一个对象,那么这个对象的数据成员也会被保存!这是能用序列化解决深拷贝的重要原因;

以上がJava のシリアル化と逆シリアル化とは何ですか? Javaのシリアライズとデシリアライズの実装方法の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

関連ラベル:
ソース:cnblogs.com
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
最新の問題
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート