シリアライズ(Serialize)
オブジェクトをバイトストリームに変換すること。
バイトストリーム
コンピュータが扱いやすい形式である0と1の列(バイナリデータ)に変換したもの。
なんでバイトストリーム化するの?
オブジェクトを保存したり、通信で送ったり、セッション情報を保持するなど、
ある機能を実装したい時、オブジェクトを直接保存したり送信することはできない場合がある。
バイトストリームに変換して扱えるようにしないと。
如何やってシリアライズさせるの?
import java.io.Serializable;
import test.他の私のクラス;
public class 私のクラス implements Serializable {
/** シリアライズするクラスに対して付与するシリアルバージョンUID **/
private static final long serialVersionUID
private String 他の私のクラス フィールド名;
...
}
シリアライズしたいクラスに java.io.Serializable インターフェースを実装する。
シリアルバージョンUIDは、シリアライズしたクラスのバージョンを識別するための一意のID。
これの役割は、シリアライズされたバイトストリームをデシリアライズする際、クラスのバージョンの整合性を確認するために使われる。
デシリアライズ(Deserialize)
シリアライズされたバイトストリームを元のオブジェクトに復元するプロセス。
今まで私、シリアライズを意識したコードを書いた記憶がないけど?
シリアライズは特定の場面で必要になるもので、普段のJava開発では直接意識しないことも多い。
オブジェクトを保存することや通信に使用しない場合、シリアライズは不要。
もしくは、使ってるフレームワークが裏側でシリアライズを処理しているケースかな。
Spring Frameworkもキャッシュ処理とかでシリアライズが必要になる場合に、自動で対応してくれる。
じゃあ、シリアライズを意識する必要ある?
シリアライズが必要になるのは、主に以下の状況:
- オブジェクトをファイルやデータベースに保存したい
- ネットワーク越しにオブジェクトを送信したい
- セッション管理(JavaのHttpSessionでオブジェクトをセッションに保存する場合)
これらを使っていない場合、シリアライズを意識する機会は少ない。
上でちょっと話したデシリアライズも同じく、保存されたデータの復元、ネットワーク通信のデータ受信、キャッシュからの復元で使われる。
上のケースでシリアライズしないとどうなる?
NotSerializableException が発生する。
NotSerializableException?
Serializableを実装していないクラスをシリアライズしようとすると出る例外。
または、クラス自体はSerializableを実装しているが、そのフィールドの一部がシリアライズ不可能なオブジェクトを持っている場合も例外が発生する。
例えばThread, Socket, FileInputStreamがある。
シリアライズ不可能なオブジェクトがある理由はなんだ
そのオブジェクトの性質や用途がシリアライズに適さないため。
プログラムの実行中にのみ有効な状態や接続を持っており、その状態をバイトストリームとして保存しても、後で復元できないことが多い。
Thread, Socket, FileInputStreamとかを含むとシリアライズ出来ないの?
この場合解決策としてtransientキーワードを使用。
import java.io.Serializable;
import test.他の私のクラス;
public class 私のクラス implements Serializable {
/** シリアライズするクラスに対して付与するシリアルバージョンUID **/
private static final long serialVersionUID
private transient String 他の私のクラス フィールド名;
...
}
transient
シリアライズしたくないフィールドを除外。これでシリアライズできない型のフィールドを回避する。
また、不要なフィールドを除外してデータサイズを削減し、パフォーマンスの向上することもできるし、
意味的にパスワードなどの機密情報や一時的な値をシリアライズ対象外にする時も使う。
結論
作ったオブジェクトについて、シリアライズが必要か、するとフィールドは含めるかなど、色々考えてみよう。
( ・。。・ )🖐
間違っている内容がありましたら、教えて頂ければ喜びます。