「オブジェクト直列化」とはどういう意味ですか?いくつか例を挙げて説明してください。
直列化は、オブジェクトを一連のバイトに変換することで、オブジェクトを永続的な記憶域に簡単に保存したり、通信リンクを介してストリーミングしたりすることができます。その後、バイトストリームを逆シリアル化して、元のオブジェクトのレプリカに変換できます。
直列化は、オブジェクトインスタンスを一連のバイト(実装によってはバイナリである場合もそうでない場合もあります)に変換するプロセスと考えることができます。
あるJVMから別のJVMなど、ネットワークを介して1つのオブジェクトデータを転送する場合に非常に便利です。
Javaでは、直列化メカニズムはプラットフォームに組み込まれていますが、オブジェクトを直列化可能にするにはSerializableインターフェースを実装する必要があります。
属性に一時的のマークを付けることで、オブジェクト内の一部のデータがシリアル化されないようにすることもできます。
最後に、デフォルトのメカニズムをオーバーライドして独自のものを提供できます。これは特別な場合に適しています。これを行うには、Javaの 隠された機能の1つ を使用します。
シリアル化されるのは、クラス定義ではなく、オブジェクトの「値」または内容であることに注意することが重要です。したがって、メソッドは直列化されていません。
これは、読みやすくするためのコメント付きの非常に基本的なサンプルです。
import Java.io.*;
import Java.util.*;
// This class implements "Serializable" to let the system know
// it's ok to do it. You as programmer are aware of that.
public class SerializationSample implements Serializable {
// These attributes conform the "value" of the object.
// These two will be serialized;
private String aString = "The value of that string";
private int someInteger = 0;
// But this won't since it is marked as transient.
private transient List<File> unInterestingLongLongList;
// Main method to test.
public static void main( String [] args ) throws IOException {
// Create a sample object, that contains the default values.
SerializationSample instance = new SerializationSample();
// The "ObjectOutputStream" class has the default
// definition to serialize an object.
ObjectOutputStream oos = new ObjectOutputStream(
// By using "FileOutputStream" we will
// Write it to a File in the file system
// It could have been a Socket to another
// machine, a database, an in memory array, etc.
new FileOutputStream(new File("o.ser")));
// do the magic
oos.writeObject( instance );
// close the writing.
oos.close();
}
}
このプログラムを実行すると、ファイル "o.ser"が作成され、何が起きているのかがわかります。
:someIntegerの値を、例えばInteger.MAX_VALUEに変更すると、出力を比較して違いがわかります。です。
これがその違いを正確に示したスクリーンショットです。
違いを見つけられますか? ;)
Javaシリアライゼーションには追加の関連フィールドがあります。 serialversionUID ですが、これをカバーするにはもう長すぎると思います。
6年前の質問に大胆に答え、Javaに不慣れな人々のための非常に高度な理解を追加する
直列化とは
オブジェクトをバイトに変換し、バイトをオブジェクトに戻します(直列化復元)。
シリアル化はいつ使用されますか。
オブジェクトを永続化したいとき。オブジェクトをJVMの存続期間を超えて存在させたい場合。
実世界の例:
ATM:口座名義人がATMを介してサーバーからお金を引き出そうとすると、引き落とし詳細などの口座名義人情報がシリアル化され、詳細が逆シリアル化されて操作の実行に使用されるサーバーに送信されます。
Javaでシリアライゼーションがどのように実行されるか。
Java.io.Serializable
インターフェースを実装します(マーカーインターフェースなので実装するメソッドはありません)。
オブジェクトを永続化します。Java.io.ObjectOutputStream
クラスを使用します。これは、低レベルのバイトストリームをラップするフィルタストリームです(Objectをファイルシステムに書き込む、またはフラット化されたオブジェクトをネットワークワイヤで転送し、反対側で再構築する)。
writeObject(<<instance>>)
- オブジェクトを書くreadObject()
- 直列化されたオブジェクトを読むため覚えておいてください:
オブジェクトをシリアル化すると、オブジェクトの状態だけが保存され、オブジェクトのクラスファイルやメソッドは保存されません。
2バイトのオブジェクトをシリアル化すると、51バイトのシリアル化ファイルが表示されます。
オブジェクトのシリアル化およびシリアル化解除の手順.
の回答:どのように51バイトのファイルに変換されましたか?
Java.lang.Object
が見つかるまでスーパークラスのメタデータを再帰的に書き出します。Javaシリアライゼーションに関するより詳細な情報に興味があるなら、この リンク をチェックしてください。
編集:もう1つ良い リンク を読んでください。
これはいくつかのよくある質問に答えます。
クラス内のフィールドをシリアル化しない方法.
回答:transientキーワードを使う
子クラスが直列化されると、親クラスは直列化されますか?
Ans:いいえ、parentが拡張可能ではない場合Serializable interface parentフィールドは直列化されません。
親が直列化されると、子クラスは直列化されますか?
回答:はい、デフォルトで子クラスもシリアライズされます。
子クラスが直列化されないようにする方法
回答:a。 writeObjectおよびreadObjectメソッドをオーバーライドしてNotSerializableException
をスローします。
b。また、子クラスですべてのフィールドを一時的にマークすることもできます。
シリアライゼーションとは、メモリ内の「生きている」オブジェクトを取り出し、それをどこか(例えば、メモリ内、ディスク上)に格納し、後で「逆シリアル化」して生きているオブジェクトに戻すことができるフォーマットに変換することである。
@OscarRyzが提示する方法が好きでした。ここで私は元々@amitguptaによって書かれた 直列化の話 を続けていますが。
ロボットのクラス構造を知り、データをシリアル化したとしても、地球の科学者はロボットを動作させることができるデータを逆シリアル化することはできませんでした。
Exception in thread "main" Java.io.InvalidClassException:
SerializeMe; local class incompatible: stream classdesc
:
火星の科学者たちは完全な支払いを待っていました。支払いが完了したら、火星の科学者たちは serialversionUID を地球の科学者たちと共有しました。地球の科学者はそれをロボットクラスに設定しました、そして、すべては大丈夫になりました。
私自身のブログから私の2セント:
これがシリアライゼーション の詳細な説明です:(私自身のブログ)
シリアル化:
直列化は、オブジェクトの状態を永続化するプロセスです。それは一連のバイトの形で表現され格納されます。これはファイルに保存できます。ファイルからオブジェクトの状態を読み取り、それを復元するプロセスは、逆シリアル化と呼ばれます。
直列化の必要性は何ですか?
現代のアーキテクチャでは、オブジェクトの状態を保存してそれを取得する必要が常にあります。例えばHibernateでは、オブジェクトを格納するためにクラスSerializableを作るべきです。つまり、オブジェクトの状態がバイトの形式で保存されると、その状態から別のシステムに転送してクラスを取得できるようになります。オブジェクトの状態は、データベース、別のJVM、または別のコンポーネントから取得できます。直列化の助けを借りて、オブジェクトの状態を取得できます。
コード例と説明:
まずItemクラスを見てみましょう。
public class Item implements Serializable{
/**
* This is the Serializable class
*/
private static final long serialVersionUID = 475918891428093041L;
private Long itemId;
private String itemName;
private transient Double itemCostPrice;
public Item(Long itemId, String itemName, Double itemCostPrice) {
super();
this.itemId = itemId;
this.itemName = itemName;
this.itemCostPrice = itemCostPrice;
}
public Long getItemId() {
return itemId;
}
@Override
public String toString() {
return "Item [itemId=" + itemId + ", itemName=" + itemName + ", itemCostPrice=" + itemCostPrice + "]";
}
public void setItemId(Long itemId) {
this.itemId = itemId;
}
public String getItemName() {
return itemName;
}
public void setItemName(String itemName) {
this.itemName = itemName;
}
public Double getItemCostPrice() {
return itemCostPrice;
}
public void setItemCostPrice(Double itemCostPrice) {
this.itemCostPrice = itemCostPrice;
}
}
上記のコードでは、ItemクラスがSerializableを実装していることがわかります。
これは、クラスを直列化可能にするためのインタフェースです。
これで、serialVersionUIDという変数がLong変数に初期化されたことがわかります。この数は、クラスの状態とクラス属性に基づいてコンパイラによって計算されます。これは、jvmがファイルからオブジェクトの状態を読み取るときに、そのオブジェクトの状態を識別するのに役立つ番号です。
そのために、公式のOracle Documentationを見てください。
直列化ランタイムは、直列化されたオブジェクトの送信側と受信側が直列化に関して互換性のあるそのオブジェクトのクラスをロードしたことを確認するために直列化解除中に使用されるserialVersionUIDというバージョン番号を各直列化可能クラスに関連付けます。受信側が、対応する送信側のクラスとは異なるserialVersionUIDを持つオブジェクトのクラスをロードした場合、逆シリアル化はInvalidClassExceptionになります。直列化可能クラスは、static、final、およびlong型でなければならない「serialVersionUID」という名前のフィールドを宣言することによって、独自のserialVersionUIDを明示的に宣言できます。ANY-ACCESS-MODIFIER static final long直列化可能クラスが明示的にserialVersionUIDを宣言しない場合、直列化ランタイムは、Java(TM)Object Serialization Specificationで説明されているように、クラスのさまざまな側面に基づいてそのクラスのデフォルトのserialVersionUID値を計算します。ただし、デフォルトのserialVersionUID計算は、コンパイラの実装によって異なるクラスの詳細に非常に敏感であり、逆シリアル化中に予期しないInvalidClassExceptionが発生する可能性があるため、すべての直列化可能クラスで明示的にserialVersionUID値を宣言することを強くお勧めします。したがって、異なるJavaコンパイラ実装間で一貫したserialVersionUID値を保証するために、直列化可能クラスは明示的なserialVersionUID値を宣言する必要があります。また、明示的なserialVersionUID宣言では可能な場合はプライベート修飾子を使用することを強くお勧めします。そのような宣言は即時宣言クラスにのみ適用されるためです。serialVersionUIDフィールドは継承メンバーとしては役に立ちません。
あなたが気づいたならば、一時的なという別のキーワードがあります。
フィールドが直列化可能でない場合は、一時的とマークする必要があります。ここでは、itemCostPriceを一時的なものとしてマークし、ファイルに書き込まないようにします。
それではファイルの中にオブジェクトの状態を書き、そこからそれを読む方法を見てみましょう。
public class SerializationExample {
public static void main(String[] args){
serialize();
deserialize();
}
public static void serialize(){
Item item = new Item(1L,"Pen", 12.55);
System.out.println("Before Serialization" + item);
FileOutputStream fileOut;
try {
fileOut = new FileOutputStream("/tmp/item.ser");
ObjectOutputStream out = new ObjectOutputStream(fileOut);
out.writeObject(item);
out.close();
fileOut.close();
System.out.println("Serialized data is saved in /tmp/item.ser");
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
public static void deserialize(){
Item item;
try {
FileInputStream fileIn = new FileInputStream("/tmp/item.ser");
ObjectInputStream in = new ObjectInputStream(fileIn);
item = (Item) in.readObject();
System.out.println("Serialized data is read from /tmp/item.ser");
System.out.println("After Deserialization" + item);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
上記で、オブジェクトのシリアライゼーションとデシリアライゼーションの例を見ることができます。
そのために2つのクラスを使いました。オブジェクトをシリアル化するために、ObjectOutputStreamを使いました。ファイルにオブジェクトを書き込むためにメソッドwriteObjectを使いました。
逆シリアル化のために、ファイルからオブジェクトから読み込むObjectInputStreamを使いました。ファイルからオブジェクトデータを読み取るためにreadObjectを使います。
上記のコードの出力は次のようになります。
Before SerializationItem [itemId=1, itemName=Pen, itemCostPrice=12.55]
Serialized data is saved in /tmp/item.ser
After DeserializationItem [itemId=1, itemName=Pen, itemCostPrice=null]
逆シリアル化されたオブジェクトのitemCostPriceは、書き込まれていないのでnullであることに注意してください。
この記事の第1部では、Javaシリアライゼーションの基本についてすでに説明しました。
それを深くそしてそれがどのように機能するかを議論しましょう。
まずはserialversionuidから始めましょう
serialVersionUIDは、Serializableクラスのバージョン管理として使用されます。
明示的にserialVersionUIDを宣言しない場合、JVMはSerializableクラスのさまざまなプロパティに基づいて自動的にそれを行います。
Javaのserialversionuid計算アルゴリズム(詳細はこちらを参照)
- クラス名
- クラス修飾子は32ビット整数として書かれています。
- 各インターフェースの名前を名前順に並べたもの。
- フィールド名でソートされたクラスの各フィールド(プライベート静的フィールドおよびプライベート一時フィールドを除く):フィールドの名前。32ビット整数として書き込まれたフィールドの修飾子。フィールドの記述子。
- クラス初期化子が存在する場合は、次のように書き出します。メソッドの名前。
- メソッドの修飾子Java.lang.reflect.Modifier.STATIC。32ビット整数として書かれています。
- メソッドの記述子()V。
- メソッド名とシグネチャでソートされた各非プライベートコンストラクタの場合:メソッドの名前。メソッドの修飾子は32ビット整数として書かれています。メソッドの記述子.
- メソッド名とシグネチャでソートされた各非プライベートメソッドの場合:メソッドの名前。メソッドの修飾子は32ビット整数として書かれています。メソッドの記述子.
- SHA-1アルゴリズムは、DataOutputStreamによって生成されたバイトストリームに対して実行され、5つの32ビット値sha [0..4]を生成します。ハッシュ値は、SHA-1メッセージダイジェストの最初と2番目の32ビット値から組み立てられます。メッセージダイジェストの結果、5つの32ビットワードH0 H1 H2 H3 H4がshaという名前の5つのint値の配列にある場合、ハッシュ値は次のように計算されます。
long hash = ((sha[0] >>> 24) & 0xFF) |
> ((sha[0] >>> 16) & 0xFF) << 8 |
> ((sha[0] >>> 8) & 0xFF) << 16 |
> ((sha[0] >>> 0) & 0xFF) << 24 |
> ((sha[1] >>> 24) & 0xFF) << 32 |
> ((sha[1] >>> 16) & 0xFF) << 40 |
> ((sha[1] >>> 8) & 0xFF) << 48 |
> ((sha[1] >>> 0) & 0xFF) << 56;
Javaのシリアライゼーションアルゴリズム
オブジェクトをシリアル化するためのアルゴリズムは、次のようになります。
1。インスタンスに関連付けられているクラスのメタデータを書き出します。
2。それはJava.lang.objectが見つかるまでスーパークラスの記述を再帰的に書き出します。
3。メタデータ情報の書き込みが完了すると、インスタンスに関連付けられている実際のデータから開始されます。しかし今回は、最上位のスーパークラスから始まります。
4。最上位スーパークラスから最派生クラスまで、インスタンスに関連付けられたデータを再帰的に書き込みます。
心に留めておくべきこと:
クラス内の静的フィールドは直列化できません。
public class A implements Serializable{
String s;
static String staticString = "I won't be serializable";
}
Serialversionuidがreadクラスと異なる場合はInvalidClassException
例外が発生します。
あるクラスが直列化可能を実装している場合、そのすべてのサブクラスも直列化可能になります。
public class A implements Serializable {....};
public class B extends A{...} //also Serializable
あるクラスが別のクラスの参照を持つ場合、すべての参照は直列化可能でなければなりません。そうでないと直列化プロセスは実行されません。そのような場合、NotSerializableExceptionが実行時にスローされます。
例えば:
public class B{
String s,
A a; // class A needs to be serializable i.e. it must implement Serializable
}
直列化は、Javaでオブジェクトを永続化することを意味します。オブジェクトの状態を保存して後でその状態を再構築したい場合(別のJVMにある場合もあります)、シリアル化を使用できます。
オブジェクトのプロパティは保存されるだけであることに注意してください。オブジェクトを再び復活させたい場合は、クラスファイルが必要です。メンバー変数だけが格納され、メンバー関数は格納されないためです。
例えば:
ObjectInputStream oos = new ObjectInputStream(
new FileInputStream( new File("o.ser")) ) ;
SerializationSample SS = (SearializationSample) oos.readObject();
Searializableは、クラスが直列化可能であることを示すマーカーインタフェースです。 Markerインタフェースは、それが単なる空のインタフェースであり、そのインタフェースを使用すると、このクラスを直列化可能にできることをJVMに通知します。
シリアル化は、オブジェクトをハードドライブに保存できるように、オブジェクトの状態をビットに変換するプロセスです。同じオブジェクトを逆シリアル化すると、後でその状態が保持されます。オブジェクトのプロパティを手動で保存しなくても、オブジェクトを再作成できます。
Java オブジェクト直列化
Serialization
は、Javaオブジェクトのグラフを格納用のバイト配列に変換するメカニズムです(to disk file
) )または転送(across a network
)を使用して、逆シリアル化を使用すると、オブジェクトのグラフを復元できます。オブジェクトのグラフは、参照共有メカニズムを使用して正しく復元されます。 ただし、保存する前に、input-file/networkのserialVersionUIDと.classファイルのserialVersionUIDが同じかどうかを確認してください。そうでなければ、Java.io.InvalidClassException
を投げます。
バージョン管理された各クラスは、それがストリームを書き込むことができ、そこから読み取ることができる元のクラスバージョンを識別する必要があります。たとえば、バージョン管理されたクラスは次のように宣言する必要があります。
serialVersionUIDの構文
// ANY-ACCESS-MODIFIER static final long serialVersionUID = (64-bit has)L; private static final long serialVersionUID = 3487495895819393L;
serialVersionUID は、シリアル化プロセスに不可欠です。しかし、開発者がそれをJavaソースファイルに追加することはオプションです。 serialVersionUIDが含まれていない場合、シリアライゼーションランタイムはserialVersionUIDを生成し、それをクラスに関連付けます。直列化されたオブジェクトは他のデータと共にこのserialVersionUIDを含みます。
注 - すべての直列化可能クラスは明示的にserialVersionUID、since the default serialVersionUID computation is highly sensitive to class details that may vary depending on compiler implementations
を宣言することを強くお勧めします。その結果、予期しないserialVersionUIDの競合が発生する可能性があります。逆シリアル化、逆シリアル化の失敗。
Javaオブジェクトは直列化のみ可能です。クラスまたはそのスーパークラスのいずれかがJava.io.Serializableインターフェースまたはそのサブインターフェースのいずれかを実装している場合、Java.io.Externalizable 。
クラスは、そのオブジェクトを正常にシリアル化するためにJava.io.Serializable interfaceを実装する必要があります。 Serializableはマーカーインタフェースであり、それを実装するクラスに直列化可能な振る舞いを追加する必要があることをコンパイラに通知するために使用されます。 ここではJava仮想マシン(JVM)が自動シリアル化を担当しています。
transientキーワード:
Java.io.Serializable interface
オブジェクトをシリアル化している間に、オブジェクトの特定のデータメンバをシリアル化したくない場合は、transient修飾子を使用できます。 transientキーワードは、そのデータメンバがシリアル化されるのを防ぎます。
- 一時的または静的として宣言されたフィールドは、直列化プロセスによって無視されます。
+--------------+--------+-------------------------------------+ | Flag Name | Value | Interpretation | +--------------+--------+-------------------------------------+ | ACC_VOLATILE | 0x0040 | Declared volatile; cannot be cached.| +--------------+--------+-------------------------------------+ |ACC_TRANSIENT | 0x0080 | Declared transient; not written or | | | | read by a persistent object manager.| +--------------+--------+-------------------------------------+
class Employee implements Serializable {
private static final long serialVersionUID = 2L;
static int id;
int eno;
String name;
transient String password; // Using transient keyword means its not going to be Serialized.
}
Externalizableインタフェースを実装すると、オブジェクトはオブジェクトの直列化形式の内容と形式を完全に制御できるようになります。 ExternalizableインタフェースのメソッドwriteExternalおよびreadExternalは、オブジェクトの状態を保存および復元するために呼び出されます。クラスによって実装されると、ObjectOutputおよびObjectInputのすべてのメソッドを使用して、独自の状態を読み書きできます。発生するバージョン管理を処理するのはオブジェクトの責任です。
class Emp implements Externalizable {
int eno;
String name;
transient String password; // No use of transient, we need to take care of write and read.
@Override
public void writeExternal(ObjectOutput out) throws IOException {
out.writeInt(eno);
out.writeUTF(name);
//out.writeUTF(password);
}
@Override
public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
this.eno = in.readInt();
this.name = in.readUTF();
//this.password = in.readUTF(); // Java.io.EOFException
}
}
Java.io.SerializableまたはJava.io.Externalizableインタフェースをサポートするオブジェクトのみがwritten to
/read from
ストリームになることができます。各直列化可能オブジェクトのクラスは、クラスのクラス名とシグネチャ、オブジェクトのフィールドと配列の値、および初期オブジェクトから参照される他のすべてのオブジェクトのクロージャを含めてエンコードされます。
ファイルのシリアライズ可能な例
public class SerializationDemo {
static String fileName = "D:/serializable_file.ser";
public static void main(String[] args) throws IOException, ClassNotFoundException, InstantiationException, IllegalAccessException {
Employee emp = new Employee( );
Employee.id = 1; // Can not Serialize Class data.
emp.eno = 77;
emp.name = "Yash";
emp.password = "confidential";
objects_WriteRead(emp, fileName);
Emp e = new Emp( );
e.eno = 77;
e.name = "Yash";
e.password = "confidential";
objects_WriteRead_External(e, fileName);
/*String stubHost = "127.0.0.1";
Integer anyFreePort = 7777;
socketRead(anyFreePort); //Thread1
socketWrite(emp, stubHost, anyFreePort); //Thread2*/
}
public static void objects_WriteRead( Employee obj, String serFilename ) throws IOException{
FileOutputStream fos = new FileOutputStream( new File( serFilename ) );
ObjectOutputStream objectOut = new ObjectOutputStream( fos );
objectOut.writeObject( obj );
objectOut.close();
fos.close();
System.out.println("Data Stored in to a file");
try {
FileInputStream fis = new FileInputStream( new File( serFilename ) );
ObjectInputStream ois = new ObjectInputStream( fis );
Object readObject;
readObject = ois.readObject();
String calssName = readObject.getClass().getName();
System.out.println("Restoring Class Name : "+ calssName); // InvalidClassException
Employee emp = (Employee) readObject;
System.out.format("Obj[No:%s, Name:%s, Pass:%s]", emp.eno, emp.name, emp.password);
ois.close();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
public static void objects_WriteRead_External( Emp obj, String serFilename ) throws IOException {
FileOutputStream fos = new FileOutputStream(new File( serFilename ));
ObjectOutputStream objectOut = new ObjectOutputStream( fos );
obj.writeExternal( objectOut );
objectOut.flush();
fos.close();
System.out.println("Data Stored in to a file");
try {
// create a new instance and read the assign the contents from stream.
Emp emp = new Emp();
FileInputStream fis = new FileInputStream(new File( serFilename ));
ObjectInputStream ois = new ObjectInputStream( fis );
emp.readExternal(ois);
System.out.format("Obj[No:%s, Name:%s, Pass:%s]", emp.eno, emp.name, emp.password);
ois.close();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
ネットワーク上の直列化可能な例
オブジェクト の状態を、同じコンピュータ上の異なるプロセス内、あるいはネットワーク経由で接続された複数のコンピュータ内など、異なるアドレス空間に分散させること。データを共有し、メソッドを呼び出すことによって一緒に。
/**
* Creates a stream socket and connects it to the specified port number on the named Host.
*/
public static void socketWrite(Employee objectToSend, String stubHost, Integer anyFreePort) {
try { // CLIENT - Stub[marshalling]
Socket client = new Socket(stubHost, anyFreePort);
ObjectOutputStream out = new ObjectOutputStream(client.getOutputStream());
out.writeObject(objectToSend);
out.flush();
client.close();
} catch (IOException e) {
e.printStackTrace();
}
}
// Creates a server socket, bound to the specified port.
public static void socketRead( Integer anyFreePort ) {
try { // SERVER - Stub[unmarshalling ]
ServerSocket serverSocket = new ServerSocket( anyFreePort );
System.out.println("Server serves on port and waiting for a client to communicate");
/*System.in.read();
System.in.read();*/
Socket socket = serverSocket.accept();
System.out.println("Client request to communicate on port server accepts it.");
ObjectInputStream in = new ObjectInputStream(socket.getInputStream());
Employee objectReceived = (Employee) in.readObject();
System.out.println("Server Obj : "+ objectReceived.name );
socket.close();
serverSocket.close();
} catch (IOException | ClassNotFoundException e) {
e.printStackTrace();
}
}
@見る
シリアル化とは、オブジェクトをファイルやメモリバッファなどの記憶媒体に保存したり、ネットワーク接続を介してバイナリ形式で転送したりする処理です。直列化されたオブジェクトはJVMに依存せず、どのJVMでも再直列化できます。この場合、「メモリ内」のJavaオブジェクトの状態はバイトストリームに変換されます。この種類のファイルは、ユーザーには理解できません。これは特別な種類のオブジェクト、つまりJVM(Java Virtual Machine)によって再利用されるオブジェクトです。オブジェクトをシリアル化するこのプロセスは、オブジェクトのデフレートまたはマーシャリングとも呼ばれます。
直列化されるオブジェクトはJava.io.Serializable
インタフェースを実装しなければなりません。オブジェクトのデフォルトのシリアル化メカニズムは、オブジェクトのクラス、クラスシグネチャ、およびすべての非一時フィールドと非静的フィールドの値を書き込みます。
class ObjectOutputStream extends Java.io.OutputStream implements ObjectOutput,
ObjectOutput
インターフェースはDataOutput
インターフェースを拡張し、オブジェクトをシリアル化してファイルにバイトを書き込むためのメソッドを追加します。 ObjectOutputStream
はJava.io.OutputStream
を拡張し、ObjectOutput
インターフェースを実装します。オブジェクト、配列、その他の値をストリームにシリアル化します。したがってObjectOutputStream
のコンストラクタは次のように書かれます。
ObjectOutput ObjOut = new ObjectOutputStream(new FileOutputStream(f));
上記のコードは、ObjectOutput
のインスタンスをパラメータとしてとるObjectOutputStream( )
コンストラクタでFileOuputStream
クラスのインスタンスを作成するために使用されてきました。
ObjectOutput
インターフェースは、ObjectOutputStream
クラスを実装することによって使用されます。 ObjectOutputStream
はオブジェクトをシリアル化するために構築されています。
Javaでオブジェクトをデシリアライズする
シリアライゼーションの逆の操作はデシリアライゼーションと呼ばれます。つまり、一連のバイトからデータを抽出することは、デシリアライゼーションとして知られています。これは、膨張または非整列化とも呼ばれます。
ObjectInputStream
はJava.io.InputStream
を拡張し、ObjectInput
インターフェースを実装します。入力ストリームからオブジェクト、配列、その他の値を逆シリアル化します。したがってObjectInputStream
のコンストラクタは次のように書かれます。
ObjectInputStream obj = new ObjectInputStream(new FileInputStream(f));
上記のプログラムのコードは、ObjectInputStream
クラスによってシリアル化されたそのファイルを逆シリアル化するためのObjectInputStream
クラスのインスタンスを作成します。上記のコードは、ObjectInputStream()
コンストラクターが入力ストリームを必要とするために逆シリアル化する必要がある指定されたファイルオブジェクトを保持するFileInputStream
クラスのインスタンスを使用してインスタンスを作成します。
ファイルをオブジェクトとして返します。 http://www.tutorialspoint.com/Java/java_serialization.htm
import Java.io.*;
public class SerializeDemo
{
public static void main(String [] args)
{
Employee e = new Employee();
e.name = "Reyan ALi";
e.address = "Phokka Kuan, Ambehta Peer";
e.SSN = 11122333;
e.number = 101;
try
{
FileOutputStream fileOut =
new FileOutputStream("/tmp/employee.ser");
ObjectOutputStream out = new ObjectOutputStream(fileOut);
out.writeObject(e);
out.close();
fileOut.close();
System.out.printf("Serialized data is saved in /tmp/employee.ser");
}catch(IOException i)
{
i.printStackTrace();
}
}
}
import Java.io.*;
public class DeserializeDemo
{
public static void main(String [] args)
{
Employee e = null;
try
{
FileInputStream fileIn = new FileInputStream("/tmp/employee.ser");
ObjectInputStream in = new ObjectInputStream(fileIn);
e = (Employee) in.readObject();
in.close();
fileIn.close();
}catch(IOException i)
{
i.printStackTrace();
return;
}catch(ClassNotFoundException c)
{
System.out.println("Employee class not found");
c.printStackTrace();
return;
}
System.out.println("Deserialized Employee...");
System.out.println("Name: " + e.name);
System.out.println("Address: " + e.address);
System.out.println("SSN: " + e.SSN);
System.out.println("Number: " + e.number);
}
}
直列化とは、Javaオブジェクトをバイト配列に変換してから、その保存された状態で再びオブジェクトに戻す処理です。オブジェクトをネットワーク経由で送信したり、物をディスクにキャッシュしたりするなど、さまざまなことに役立ちます。
プロセスのプログラミング部分を非常によく説明しているこの短い記事 それから に移動して/ - 直列化可能なjavadoc に進んでください。 この関連質問 を読むことにも興味があるかもしれません。
| * |クラスの直列化:オブジェクトをバイトに変換し、バイトをオブジェクトに戻す(逆シリアル化)。
class NamCls implements Serializable
{
int NumVar;
String NamVar;
}
| =>オブジェクト直列化は、オブジェクトの状態をSteam of bytesに変換するプロセスです。
| =>オブジェクトの逆シリアル化は、オブジェクトの状態を取得し、それをオブジェクト(Java.lang.Object)に格納するプロセスです。
| => Javaオブジェクトは、そのクラスまたはそのスーパークラスのいずれかに該当する場合にのみ直列化可能です。
| =>クラス内の静的フィールドは直列化できません。
class NamCls implements Serializable
{
int NumVar;
static String NamVar = "I won't be serializable";;
}
| =>クラスの変数を直列化したくない場合はtransientキーワードを使用してください。
class NamCls implements Serializable
{
int NumVar;
transient String NamVar;
}
| =>クラスが直列化可能を実装している場合、そのすべてのサブクラスも直列化可能になります。
| =>あるクラスが他のクラスの参照を持つ場合、すべての参照は直列化可能でなければなりません。そうでなければ直列化プロセスは実行されません。このような場合には、
NotSerializableExceptionが実行時にスローされます。