Javaシーケンス化メカニズム

3983 ワード

一、なぜシーケンス化するのか.
1.一般的に、Javaオブジェクトは、JVMが実行されている場合にのみ存在します.つまり、これらのオブジェクトのライフサイクルはJVMのライフサイクルよりも長くはありません.しかし、現実的なアプリケーションでは、JVMが停止した後に指定したオブジェクトを保存(永続化)し、保存されたオブジェクトを将来再読み込みする必要がある場合があります.Javaオブジェクトのシーケンス化は、この機能を実現するのに役立ちます.
2、ネットワークまたはプロセス通信でオブジェクトを転送する場合、シーケンス化を使用してJavaオブジェクトをバイトシーケンス転送に変換する必要があります.具体的には、データを送信する前にオブジェクトをシーケンス化し、データを受信した後にオブジェクトを逆シーケンス化します.
二、シーケンス化とは何ですか.
シーケンス化とは、シーケンス化を実現するJavaオブジェクトをディスクに保存したり、ネットワークを介して転送したりして、後で元のオブジェクトに復元できるバイトシーケンスに変換することを許可することです.シーケンス化メカニズムにより、オブジェクトはプログラムの実行から独立して存在することができる.
分かりやすく言えば、Javaシーケンス化とは、Javaオブジェクトをバイトシーケンスに変換するプロセスであり、Java逆シーケンス化とは、バイトシーケンスをJavaオブジェクトに復元するプロセスである.
三、Javaシーケンス化メカニズム
1.Serializableインタフェースによるシーケンス化
Javaでは1つのクラスだけjavaが実現する.io.Serializableインタフェースは、シーケンス化できます.
@Data
public class UserA implements Serializable {
    /**
     *    ID
     */
    private static final long serialVersionUID = 1L;

    private int age;
    private static String name = "  ";

    @Override
    public String toString() {
        return "User{age=" + age + ",name=" + name + "}";
    }    
}

2.Externalizableインタフェースによるシーケンス化
ExternalizableはSerializableインタフェースから継承されています.writeExternal()とreadExternal()メソッドを書き換えて、どの情報をシーケンス化するかを決定し、publicのパラメトリックなコンストラクタを提供する必要があります.
Externalizableの性能はSerializableより優れているが、複雑さも増している.
@Data
public class UserB implements Externalizable {
    /**
     *    ID
     */
    private static final long serialVersionUID = 1L;

    private int age;
    private static String name = "  ";


    @Override
    public void writeExternal(ObjectOutput out) throws IOException {
        out.writeInt(age);
    }

    @Override
    public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
        age = in.readInt();
    }

    @Override
    public String toString() {
        return "User{age=" + age + ",name=" + name + "}";
    }
}

3.シーケンス化と逆シーケンス化
SerializableインタフェースまたはExternalizableインタフェースを実現することで、Javaオブジェクトはすでにシーケンス化の資質を備えていますが、どのようにシーケンス化と逆シーケンス化を行うのでしょうか.ここではObjectOutputStreamとObjectInputStreamを用いてオブジェクトをシーケンス化および逆シーケンス化した.
    public static void main(String[] args) {
        //    
        serialize();
        //     
        deserialize();
    }

    private static void serialize() {
        UserA user = new UserA();
        user.setAge(26);
        //         
        try (ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream("D:\\userA"))) {
            objectOutputStream.writeObject(user);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private static void deserialize() {
        try (ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream("D:\\userA"))) {
            UserA user = (UserA) objectInputStream.readObject();
            System.out.println(user);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }

四、シーケンス化分析
  • serialVersionUID、すなわちシーケンス化ID.仮想マシンが逆シーケンス化できるかどうかは、クラスパスと機能コードが一致しているかどうかだけでなく、2つのクラスのシーケンス化IDが一致しているかどうかが重要です.そうしないと、逆シーケンス化時にInvalidClassException異常が放出されます.serialVersionUIDのデフォルトは1 Lで、指定を表示しなくてもよい.
  • 静的変数はシーケンス化されません.静的変数は仮想マシンメソッド領域に存在し、グローバル変数に属するため、シーケンス化または逆シーケンスの場合、静的変数は保存されません.
  • transientキーワード.変数のシーケンス化を制御し、変数宣言前にキーワードを付けることで、変数がファイルにシーケンス化されるのを阻止し、逆シーケンス化された後、transient変数の値をint型が0、オブジェクト型がnullなどの初期値に設定することができます.
  • 親子クラスのシーケンス化.親オブジェクトもシーケンス化するには、親もSerializable(またはExternalizable)インタフェースを実装する必要があります.
  • は、タイプメンバー変数のシーケンス化を参照します.参照オブジェクトをシーケンス化するには、参照オブジェクトにもSerializable(またはExternalizable)インタフェースを実装する必要があります.