JavaのSerializableシーケンス化と逆シーケンス化

11154 ワード

JavaのSerializableシーケンス化と逆シーケンス化
シーケンス化の基本概念:
シーケンス化:オブジェクトをバイトシーケンス化に変換するプロセスをオブジェクトのシーケンス化と呼びます.逆シーケンス化:バイトシーケンスをオブジェクトに復元するプロセスをオブジェクトの逆シーケンス化と呼ぶ.
シーケンス化が必要な場合
メモリ内のオブジェクトのステータスをファイルまたはデータベースに保存したい場合.ソケットでネットワーク上でオブジェクトを転送したい場合.RMIを介してオブジェクトを転送したい場合.深さcloneが必要な場合にシーケンス化と逆シーケンス化を行っても新しいオブジェクトが得られます(詳細には設計モードのプロトタイプモードが可能です)
シーケンス化の実装
Serializableインタフェースの実装
2つのクラスを設定:アドレスクラス
public class Address implements Serializable{

    String pro;
    String city;
    String zip;

    public Address(String p,String c,String z){
        pro = p;city=c;zip =z;
    }

    public String getPro() {
        return pro;
    }

    public void setPro(String pro) {
        this.pro = pro;
    }

    public String getCity() {
        return city;
    }

    public void setCity(String city) {
        this.city = city;
    }

    public String getZip() {
        return zip;
    }

    public void setZip(String zip) {
        this.zip = zip;
    }
}

個人情報クラス
public class Student  implements Serializable{

private static final long serialVersionUID = 1L;

    String name;
    int age;
    Address add; //     

   public Student(String na,int a,Address add){
        this.name = na;
        this.age = a;
        this.add = add;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public Address getAdd() {
        return add;
    }

    public void setAdd(Address add) {
        this.add = add;
    }
}

テスト実装クラス(springbootでテストした無視上@注釈です)


@RunWith(SpringRunner.class)
@SpringBootTest(classes = TaotaoApplication.class)
@ContextConfiguration
public class PortotypeTest {

    @Test
    public void testPorto()throws IOException{

        Address address = new Address("   ","   ","300000");
        Student student = new Student("tom",22, address);

        //      
        ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream(new File("c:/student.txt")));
        objectOutputStream.writeObject(student); //    
        objectOutputStream.close();
    }

    @Test
    public void testPortoReturn() throws Exception{
        ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream(new File("c:/student.txt")));
        Student student = (Student) objectInputStream.readObject();
        System.out.println( student.getName());
        System.out.println( student.getAge());
        System.out.println( student.getAdd().getCity());

    }
//           
//    2018-06-07 21:46:06,794:INFO main (StartupInfoLogger.java:57) - Started PortotypeTest in 2.622 seconds (JVM running for 3.979)
//    tom
//    22
//       
}

testPortoはシーケンス化操作テストのためにstudentを正常に開くと内容が表示されます
testPortoReturnは逆シーケンス化されています注意ここでaddressもSerializableインタフェースを実装する必要があります.そうしないとシーケンス化と逆シーケンス化は実現されません.
注意シーケンス化されない場合
1 staticキーワード修飾の変数
studentにプロパティフィールドを追加します.
public static String shotname = "to";

ファイルにシーケンス化してshotnameの値を変更
public static String shotname = "to555";

逆シーケンス化(シーケンス化に成功した場合shotnameの値はto)を実行します.
    @Test
    public void testPortoReturn() throws Exception{
        ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream(new File("c:/student.txt")));
        Student student = (Student) objectInputStream.readObject();
        System.out.println( student.getName());
        System.out.println( student.getAge());
        System.out.println( student.getShotname());
        System.out.println( student.getAdd().getCity());

    }

結果:
2018-06-07 21:59:51,262:INFO main (StartupInfoLogger.java:57) - Started PortotypeTest in 2.738 seconds (JVM running for 4.119)
tom
22
to555
   

status修飾変数はシーケンス化されません
2 transient修飾変数
実際の開発の過程で、このクラスのいくつかの属性はシーケンス化する必要がありますが、他の属性はシーケンス化する必要はありません.例えば、ユーザーがパスワード、銀行カード番号などの機密情報を持っている場合は、セキュリティのためにネットワークで操作したくない(主にシーケンス化操作に関し、ローカルシーケンス化キャッシュも適用される)で転送され、これらの情報に対応する変数にtransientキーワードを付けることができます.言い換えれば、このフィールドのライフサイクルは、ディスクに書き込まずに呼び出し元のメモリにのみ保存されます.(具体的なコードはstatusに似ています).
serialVersionUID = 1L
次の行のコードを説明します.
private static final long serialVersionUID = 1L;

シーケンス化の実行時にserialVersionUIDと呼ばれるバージョン番号を使用すると、シーケンス化可能な各クラスに関連付けられます.このシーケンス番号は、逆シーケンス化中にシーケンス化されたオブジェクトの送信者と受信者がシーケンス化と互換性のあるクラスをロードしたかどうかを検証するために使用されます.受信者がロードしたオブジェクトのクラスのserialVersionUIDが、対応する送信者のクラスのバージョン番号と異なる場合、逆シーケンス化によってInvalidClassExceptionが発生します.直列可能クラスは、「serialVersionUID」という名前のフィールド(このフィールドは静的(static)、最終(final)のlong型フィールドである必要がある)を宣言することによって、独自のserialVersionUIDを明示的に宣言することができる.
シーケンシング可能クラスがserialVersionUIDを明示的に宣言していない場合、「Java(TM)オブジェクトシーケンシング仕様」に記載されているように、シーケンシング実行時にクラスのさまざまな態様に基づいてクラスのデフォルトserialVersionUID値が計算されます.ただし、デフォルトのserialVersionUIDを計算することは、クラスの詳細情報に高い感度を持ち、コンパイラによっては千差万別の可能性があり、逆シーケンス化中に予期せぬInvalidClassExceptionを引き起こす可能性があるため、すべてのシーケンス化可能なクラスに対してserialVersionUID値を明示的に宣言することを強くお勧めします.したがって、serialVersionUID値が異なるjavaコンパイラで実現される一貫性を保証するために、シーケンス化クラスは明確なserialVersionUID値を宣言する必要があります.private修飾子を使用して宣言serialVersionUIDを表示することも強くお勧めします.(可能な場合)、この宣言は直接宣言クラス-serialVersionUIDフィールドのみが継承メンバーとして適用されるため、使用できません.配列クラスは明確なserialVersionUIDを宣言できないため、常にデフォルトの計算値を持っていますが、配列クラスはserialVersionUID値の要件に一致していません.
つまり、シーケンス化に使用して値を設定することをお勧めします.そうしないと、シーケンス化に成功した後、逆シーケンス化されます.値が一致しないと、NotSerializableExceptionに報告されます.