オブジェクト向け-Javaオブジェクトのシーケンス化
シーケンス化の概要
簡単に言えばシーケンス化はオブジェクトストリームを処理するためのメカニズムであり、オブジェクトストリームとはオブジェクトの内容をストリーミングすることであり、ストリームの概念はここでは言うまでもなく(I/Oである)、ストリーミング後のオブジェクトに対して読み書き操作を行うこともできるし、ストリーミング後のオブジェクトをネットワーク間に転送することもできる(注:オブジェクトをネットワークに転送するにはストリーミングを行う必要がある)!オブジェクトストリームの読み書き操作で問題が発生しますが、シーケンス化メカニズムはこれらの問題を解決するために使用されます.
問題の引き出し:
以上のように読み書き対象にはどのような問題があるのでしょうか.たとえば、オブジェクトをディスクファイルに書き込んでから読み込むと何か問題がありますか?焦らないでください.最大の問題はオブジェクト参照です.たとえば、AとBの2つのクラスがある場合、BクラスにはAクラスオブジェクトへの参照が含まれています.次に、2つのクラスをインスタンス化します{A a=new A();B b=new B()}.このとき、メモリには実際に2つの空間が割り当てられ、1つのストレージオブジェクトa、1つのストレージオブジェクトbが割り当てられます.次に、ディスクのファイルに書き込むと、ファイルに書き込むときに問題が発生します.オブジェクトbにはオブジェクトaへの参照が含まれているため、システムは自動的にaのデータをbにコピーします.そうすると、ファイルからオブジェクトを復元するとき(つまりメモリに再ロードするとき)にメモリに3つの空間が割り当てられ、オブジェクトaは同時にメモリに2つ保存されます.結果を考えてみましょう.オブジェクトaのデータを変更したい場合は、それは、オブジェクトデータの一貫性を達成するためにコピーを検索する必要はありません.これは私たちが望んでいるものではありません.
次のシーケンス化メカニズムのソリューション:
1.ディスクに保存されているすべてのオブジェクトについて、シリアル番号(1、2、3など)を取得します.
2.オブジェクトを保存する場合は、オブジェクトが保存されているかどうかを確認します.
3.以前に保存した場合は、「保存したシリアル番号xを持つオブジェクトと同じ」というタグを書き込むだけで、そうでない場合は、そのオブジェクトを保存します.
以上の手順でシーケンス化メカニズムによりオブジェクト参照の問題を解決しました!
シーケンス化の実装
シーケンス化する必要があるクラスには、実装する必要がないSerializableインタフェースが実装されます.implements Serializableは、オブジェクトがシーケンス化可能であることを示すためにのみ、出力ストリーム(FileOutputStreamなど)を使用してObjectOutputStreamオブジェクトを構築し、次にObjectOutputStreamオブジェクトのwriteObject(Object obj)を使用します.メソッドはパラメータobjのオブジェクトを書き出し(すなわちその状態を保存)することができ,復元するには入力ストリームを用いる.
例:
デフォルトのシーケンス化メカニズムの変更
シーケンス化の過程で、一部のデータフィールドはシーケンス化したくない.このようなフィールドについては、定義時にtransientキーワードを付けるだけでよい.transientフィールドシーケンス化メカニズムでは、ファイルに書き込まないことをスキップし、リカバリすることはできない.しかし、あるフィールドをシーケンス化したい場合がありますが、SDKでの定義はシーケンス化できないタイプです.そうすると、transientと表記しなければなりませんが、書き込めないとどうやって復元しますか?シーケンス化メカニズムは、このような特殊な問題を含むクラスに次の方法で定義されています.
(注:これらのメソッドは、呼び出しを表示する必要がないため、シーケンス化メカニズムが自動的に呼び出される)以上の方法を使用して、シーケンス化したいデータフィールドやシーケンス化できないデータフィールドを手動で書き出したり読み込んだりすることができます.次の例では、java.awt.geomパッケージのPoint 2 D.Doubleクラスはシーケンス化できません.このクラスはSerializableインタフェースを実装していないため、私の例ではLabeledPointクラスのデータフィールドとして使用し、シーケンス化方法を示します.
変換元:http://www.oracle-bbs.com/oracle_forum_MianXiangDuiXiangJavaDuiXiangXuLieHua-sql-database-0-287079.html
簡単に言えばシーケンス化はオブジェクトストリームを処理するためのメカニズムであり、オブジェクトストリームとはオブジェクトの内容をストリーミングすることであり、ストリームの概念はここでは言うまでもなく(I/Oである)、ストリーミング後のオブジェクトに対して読み書き操作を行うこともできるし、ストリーミング後のオブジェクトをネットワーク間に転送することもできる(注:オブジェクトをネットワークに転送するにはストリーミングを行う必要がある)!オブジェクトストリームの読み書き操作で問題が発生しますが、シーケンス化メカニズムはこれらの問題を解決するために使用されます.
問題の引き出し:
以上のように読み書き対象にはどのような問題があるのでしょうか.たとえば、オブジェクトをディスクファイルに書き込んでから読み込むと何か問題がありますか?焦らないでください.最大の問題はオブジェクト参照です.たとえば、AとBの2つのクラスがある場合、BクラスにはAクラスオブジェクトへの参照が含まれています.次に、2つのクラスをインスタンス化します{A a=new A();B b=new B()}.このとき、メモリには実際に2つの空間が割り当てられ、1つのストレージオブジェクトa、1つのストレージオブジェクトbが割り当てられます.次に、ディスクのファイルに書き込むと、ファイルに書き込むときに問題が発生します.オブジェクトbにはオブジェクトaへの参照が含まれているため、システムは自動的にaのデータをbにコピーします.そうすると、ファイルからオブジェクトを復元するとき(つまりメモリに再ロードするとき)にメモリに3つの空間が割り当てられ、オブジェクトaは同時にメモリに2つ保存されます.結果を考えてみましょう.オブジェクトaのデータを変更したい場合は、それは、オブジェクトデータの一貫性を達成するためにコピーを検索する必要はありません.これは私たちが望んでいるものではありません.
次のシーケンス化メカニズムのソリューション:
1.ディスクに保存されているすべてのオブジェクトについて、シリアル番号(1、2、3など)を取得します.
2.オブジェクトを保存する場合は、オブジェクトが保存されているかどうかを確認します.
3.以前に保存した場合は、「保存したシリアル番号xを持つオブジェクトと同じ」というタグを書き込むだけで、そうでない場合は、そのオブジェクトを保存します.
以上の手順でシーケンス化メカニズムによりオブジェクト参照の問題を解決しました!
シーケンス化の実装
シーケンス化する必要があるクラスには、実装する必要がないSerializableインタフェースが実装されます.implements Serializableは、オブジェクトがシーケンス化可能であることを示すためにのみ、出力ストリーム(FileOutputStreamなど)を使用してObjectOutputStreamオブジェクトを構築し、次にObjectOutputStreamオブジェクトのwriteObject(Object obj)を使用します.メソッドはパラメータobjのオブジェクトを書き出し(すなわちその状態を保存)することができ,復元するには入力ストリームを用いる.
例:
- import java.io.*;
- -----------------------------------------------------------
- class Employee implements Serializable
-
- {
- public Employee(String n, double s)
- {
- name = n;
- salary = s;
- }
-
- /**
- *
- */
-
- public void raiseSalary(double byPercent)
-
- {
- double raise = salary * byPercent / 100;
- salary += raise;
- }
-
- public String toString()
-
- {
- return getClass().getName()
- + "[name = "+ name
- + ",salary = "+ salary
- + "]";
- }
-
- private String name;
- private double salary;
- }
-
-
- class Manager extends Employee
- {
- public Manager(String n, double s)
- {
- super(n, s);
- secretary = ;
- }
-
-
- /**
- *
- */
-
- public void setSecretary(Employee s)
-
- {
- secretary = s;
- }
-
- public String toString()
-
- {
-
- return super.toString()
- + "[secretary = "+ secretary
- + "]";
-
- }
- //secretary
- private Employee secretary;
- }
デフォルトのシーケンス化メカニズムの変更
シーケンス化の過程で、一部のデータフィールドはシーケンス化したくない.このようなフィールドについては、定義時にtransientキーワードを付けるだけでよい.transientフィールドシーケンス化メカニズムでは、ファイルに書き込まないことをスキップし、リカバリすることはできない.しかし、あるフィールドをシーケンス化したい場合がありますが、SDKでの定義はシーケンス化できないタイプです.そうすると、transientと表記しなければなりませんが、書き込めないとどうやって復元しますか?シーケンス化メカニズムは、このような特殊な問題を含むクラスに次の方法で定義されています.
- private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException;
- private void writeObject(ObjectOutputStream out) throws IOException;
(注:これらのメソッドは、呼び出しを表示する必要がないため、シーケンス化メカニズムが自動的に呼び出される)以上の方法を使用して、シーケンス化したいデータフィールドやシーケンス化できないデータフィールドを手動で書き出したり読み込んだりすることができます.次の例では、java.awt.geomパッケージのPoint 2 D.Doubleクラスはシーケンス化できません.このクラスはSerializableインタフェースを実装していないため、私の例ではLabeledPointクラスのデータフィールドとして使用し、シーケンス化方法を示します.
- import java.io.*;
- import java.awt.geom.*;
-
- public class TransientTest
- {
- public static void main(String[] args)
- {
- LabeledPoint label = new LabeledPoint("Book", 5.00, 5.00);
- try
- {
- System.out.println(label);//
- ObjectOutputStream out = new ObjectOutputStream(new
- FileOutputStream("Label.txt"));
- out.writeObject(label);
- out.close();
- System.out.println(label);//
- ObjectInputStream in = new ObjectInputStream(new
- FileInputStream("Label.txt"));
- LabeledPoint label1 = (LabeledPoint)in.readObject();
- in.close();
- System.out.println(label1);// 1.0
- }
- catch (Exception e)
- {
- e.printStackTrace();
- }
- }
- }
-
変換元:http://www.oracle-bbs.com/oracle_forum_MianXiangDuiXiangJavaDuiXiangXuLieHua-sql-database-0-287079.html