Javaプログレッシブ化の問題

6929 ワード

【本文は転載のために、忘れ物をするために、その例を修正しました.原文の住所:http://liu-hliang.iteye.com/blog/748356、原作者に感謝します.】
 
   Javaオブジェクトをバイトシーケンスに変換するプロセスをオブジェクトの順序と呼びます.   バイトシーケンスをJavaオブジェクトに復元するプロセスをオブジェクトの逆順序化と呼びます.   avaに導入されるプログレッシブ機構は主に2つの重要な技術をサポートするためである.RMIとJavaBean技術.   
    オブジェクトの順序は主に2つの用途があります.1)オブジェクトのバイトシーケンスをハードディスクに永久に保存し、通常は一つのファイルに保存します.2)オブジェクトのバイトシーケンスをネットワーク上で送信する.   SerializableとExternalizableインターフェースを実現した類のオブジェクトだけが、プログレッシブされます.      1)Serializableインターフェースは、クラス内のすべてのメンバー変数が自動的にプロローグされ、デフォルトの           プログレッシブ方式は、オブジェクト図全体を逐次的に並べ、オブジェクト図を再帰的に巡回する必要があります.オブジェクト図が複雑である場合、再帰的に巡回するには多くの費用がかかります.           の空間と時間、その内部データ構造は双方向リストです.アプリケーションでは、いくつかのメンバー変数をtranientタイプに変更すると、           スペースと時間を節約して、序文化の性能を高めます.      2)ExternalizableインターフェースはSerializableインターフェースから継承され、Externalizableインターフェースを実現するクラスは完全に自身で序列化を制御します.           は、Externalizableオブジェクトのデフォルトの場合は、そのフィールドは保存されません.Serializableインターフェースのクラスだけが可能です.           デフォルトのプログレッシブ方式を採用します.   私たちはどのようにSerializableオブジェクトの序列化と反順序化の行動を制御しますか?      1)tranient修繕符を入れると、量が変わるので、順番に並べられなくなります.      2)追加(「実現」と「再負荷」ではない)writeObjectとreadObject方法:privte void writeObject(Object Output Stream stream)throws IOException;privte void readObject(Object Output Stream stream)throws IOException;
     このように、オブジェクトがプログレッシブ化されると、または逆プログレッシブ化されると、それぞれの方法が起動され、デフォルトのプログレッシブおよび逆プログレッシブ方法が起動されなくなります.(この点は確かにおかしいと思います.あるいは混乱しています.)    Object OutputStreamがSerializableオブジェクトをプロビジョニングする場合、オブジェクトがwriteObject()メソッドを持っているなら、この方法を実行します.そうでなければ、デフォルトでプロビジョニングします.このオブジェクトのwriteObject()方法では、まずObject Output Streamのdefault WriteObject()メソッドを呼び出して、オブジェクト出力ストリームがデフォルトの順序付け操作を先に実行させることができる.それと同じように、アンチプログレッシブな状況が得られますが、今回はdefault ReadObject()の方法です.
Serializableオブジェクトに対して逆プログレッシブ化すると、いかなるコンストラクタも起動しないので、Serializable類はデフォルトのコンストラクタは必要ないですが、Serializable類の親がSerializableインターフェースを実現していない場合、アンチプログレッシブプロセスは親類のデフォルトのコンス関数を呼び出します.
 
  #
Externalizableオブジェクトの順を逆にすると、クラスのパラメータを持たない構造方法が呼び出されます.これはデフォルトの逆シーケンス方式とは違っています.クラスのパラメータを持たない構造方法を削除するか、またはこの構造方法のアクセス権限をprvate、デフォルトまたはprotectedレベルに設定すると、java.io.InvalidExceptio:no valid constructorに異常があるため、Externalizableオブジェクトにはデフォルトの構成関数が必要であり、publicが必要です.
ヒドイオブジェクトの順序付けは、ファイル出力フローなどの他のタイプのターゲット出力ストリームを包装することができるオブジェクト出力ストリームを作成するステップを含む.2)オブジェクト出力ストリームのwriteObject()方法でオブジェクトを書きます.オブジェクトの逆順序化のステップは、以下の通りである.1)オブジェクト入力ストリームを作成し、ファイル入力ストリームのような他のタイプのソース入力ストリームを包装することができる.2)オブジェクト入力ストリームのreadObject()方法でオブジェクトを読み出す.以下は簡単な例です.
 
class Animal {
    Animal() {
        System.out.print("a");
    }
}

class Dog extends Animal implements Serializable {
    private static final long serialVersionUID = 1L;
    Dog() {
        System.out.print("d");
    }
}
class Beagle extends Dog {
    private static final long serialVersionUID = 1L;
}


public class Test {
    public static void main(String[] args) {
        Beagle bg = new Beagle();
        try {
            //   
            FileOutputStream fos = new FileOutputStream("myobj.ser");
            ObjectOutputStream oos = new ObjectOutputStream(fos);
            oos.writeObject(bg);
            oos.flush();
            oos.close();

            //    
            FileInputStream fis = new FileInputStream("myobj.ser");
            ObjectInputStream ois = new ObjectInputStream(fis);
            bg = (Beagle)ois.readObject();
            ois.close();

            System.out.println(bg.master.name);

        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e){
            e.printStackTrace();
        } catch(ClassNotFoundException e){
            e.printStackTrace();
        }
    }
}
    出力:ada
 
 
 
    serialVersion UIDについて:    Loong(当社が独自に開発したOGIベースのネットワークアプリケーションサーバプラットフォーム)でGlassfishのデータソースを統合する際に、プログレッシブ化された問題に遭遇しました.Glassfishにおいて、プログレッシブ化された接続プールのオブジェクトは、Loongにおいて、プログレッシブ化された時にはいつも成功しません.その後、関連資料を調べましたが、接続池類に問題がありました.Serializableインターフェースだけ実現しました.具体的なserialVerssionUIDは指定されていません.    Serializableインターフェースを実現するすべてのクラスには、プログレッシブバージョンの識別子を示す静的変数があるべきである.prvate static final long serialVerssionUID.
    以上のserialVersion UIDの取得値はJava実行時に環境がクラスの内部詳細によって自動的に生成されます.クラスのソースコードを修正して再コンパイルすれば、新たに作成したクラスファイルのserialVersion UIDの取得値も変化する可能性があります.
クラスのserialVersionUIDのデフォルト値はJavaコンパイラの実現に完全に依存しています.同じクラスに対して、異なるJavaコンパイラでコンパイルすると、異なるserialVerssionUIDを引き起こす可能性があります.オーストリアVersioniUIDの独立性と確定性を向上させるために、プログレッシブクラスに表示される定義セリルVersion UIDに明確な値を与えることを強く提案します.    serialVersioniUIDを明示的に定義するには、2つの用途があります.1)場合によっては、希望クラスの異なるバージョンは、序列化互換性があるので、クラスの異なるバージョンが同じserialVersioniUIDを有することを保証する必要があります.2)場合によっては、クラスの異なるバージョンは、序文化と互換性があることを望まないので、クラスの異なるバージョンが異なるserialVersion UIDを持つことを確保する必要があります.Javaの序文化とアンチプログレッシブ機構を利用して、任意のSerializableのオブジェクトに対する深さコピーを実現することができる.    上記の例では、MyObjectオブジェクトをハードディスクファイルcに順列化し、逆順序化して深さコピーを実現できますが、ハードディスクの操作により頻繁にシステム性能に大きな影響を与えます.上記はファイルフロー方式で実現されています.バイトストリーム方式で効率的に深さコピーができます.
 
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.util.Date;


public class Test{
    public static void main(String[] args) throws Exception {
        //     
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        ObjectOutputStream out = new ObjectOutputStream( bos);
        MyObject obj1= new MyObject("John", 24);
        out.writeObject("hello world!");
        out.writeObject(new Date());
        out.writeObject(obj1);
        out.writeInt(54);
        out.close();

        //      
        ObjectInputStream in = new ObjectInputStream( new ByteArrayInputStream(bos.toByteArray()));
        System.out.println("obj1=" + (String) in.readObject());
        System.out.println("obj2=" + (Date) in.readObject());
        MyObject obj3 = (MyObject) in.readObject();
        System.out.println("obj3=" + obj3);
        int obj4 = in.readInt();
        System.out.println("obj4=" + obj4);
        in.close();
      }
 }
//        
class MyObject implements Serializable {
    private static final long serialVersionUID = 1L;
    private String name;
    private int age;
    public MyObject(String name, int age) {
        this.name = name; this.age = age;
    }
    public String toString() {
        return "name=" + name + ", age=" + age;
    }
}