[Java]java.io.SerializableのSerializable(直列化可能)とは何なのか?
AppFuseで生成されたクラスたちの中でも、Modelにあたるクラスは、大体が「implements Serializable」している。
改めて「うーん」と考えた(いや考えてない、調べて理解するのに頭を使っただけ)、java.io.Serializableインタフェースってなんだ?
先ずはリファレンスを参照してみた。
クラスの直列化可能性は、java.io.Serializable インタフェースを実装したクラスによって有効になります。このインタフェースを実装していないクラスでは、その状態が直列化または直列化復元されることはありません。直列化可能クラスのサブタイプは、すべてそれ自体が直列化可能です。直列化インタフェースにはメソッドやフィールドはなく、直列化可能であることを識別するためだけに機能します。
Serializable (Java 2 Platform SE 5.0)より引用
「直列化可能」にしてくれるインタフェースらしい。
でも「直列化可能」って何だ!電池でもないのにクラスが直列になるの?
そういえば理科の時間にやった電池の直列、並列も苦手だったな。
長持ちする方を選べとか、豆電球が明るく光る方を選べとか・・・電池を大量に買えばいいから、この問題は解けなくても構わないや、と投げた気がする。
走馬灯のように駆け巡る電池の思い出はさておいて、母語とは思えないほど「直列化可能」という言葉の意味が分からないので、検索、ITアーキテクトで解説を発見。
インタフェースSerializableは、メソッドやフィールドを1つも持たない空のインタフェース(マーカ・インタフェース)です。このインタフェースは、それをimplementsするオブジェクトがシリアライズ可能であることを示すためだけに機能します。
Javaの“常識”、“非常識” 第3回 - ITアーキテクト [IT Architect]より引用
しまった、「直列化可能」が分からないから検索してたのに、もうひとつ「分からない新しい言葉」が出てきた。
シリアライズ可能?これって「直列化可能」と同じ意味?
分からないので訳してみた。
* serializable
【名】
《コ》直列化可能
“Serializable”の検索結果(1 件):英辞郎 on the Web:スペースアルクより引用
全く同じだ。
「Serializable=直列化可能」、ここまでは分かった。
Serializableインタフェースは、名前のとおり「Serializableインタフェースをimplementsしたクラス」が、直列化可能であることを示すためだけに機能する、ということのようです。
でも「Serializable」という言葉の意味も、「直列化可能」という言葉の意味もまだ分からない。
英英辞書か国語辞典かで迷いながら再度検索、よくお世話になるTECHSCOREが引っかかった。
任意のクラスのデータをファイルに保存したり、ファイルから復元したりする事が考えられます。独自に保存・復元のプログラムを記述する事も可能ですが、 Javaでは簡単にこの仕組みを実現できる機能が提供されています。(中略)あるクラスのオブジェクトが保存・復元できる事を、「直列化可能である」と言います。また保存・復元できるかどうかを「直列化可能性」と呼びます。
オブジェクトのシリアライズ入出力-TECHSCORE-より引用
「生成されたオブジェクトのデータを、ファイルやDBに対して保存・復元出来る」
そういうクラスのことを「Serializable(直列化可能)なクラス」と呼ぶらしい。
じゃあAppFuseで自動生成されたModelのクラスたちは、みんな「Serializable(直列化可能)なクラス」だったのか、確かにデータ出し入れしてたものね。
納得しかけたら稚内北星学園大学のJavaBeansに関する資料を見つけた。
Bean は、必要に応じてオブジェクトの状態を保存したり、復元したりすることができなければいけません。このことを、Beanを「永続化」する、といいます。このためには、Beanにjava.io.Serializableインタフェースを実装する必要があります。このインタフェースにはメソッドは定義されていないので、次のように定義するだけで構いません。
2003年度 ソフトウェア特論より引用
「直列化可能」、「Serializable」ときて今度は「永続化」ですか、そうですか、多分同じ意味だよね?
不安になったのでもう少し調べる。
もうひとつ、JavaBeansの仕様では、Java Beanクラスは「直列化可能」である必要がある。
Java Beanクラスは、プロパティに格納した情報を保存できる必要があるため、Serializableインターフェイスの実装クラスとする必要がある。(中略)これは絶対必要な条件ではない。実際、通常のサーブレットとJSPで使用する場合には直列化可能である必要はない。ただし、システムによっては必要不可欠であるため、Serializableインターフェイスの実装クラスとしておいた方が安全だろう。
JavaA2Z【JavaBeansとは】より引用
Modelのクラスたちは、プロパティに格納した情報をDBに渡したり、DBから受け取ったりするための部品(JavaBeans)なので、「Serializable(直列化可能)」でなければいけない、と。
でも、さっき「Serializable(直列化可能)なクラス」というのは、「生成されたオブジェクトのデータを、ファイルやDBに対して保存・復元出来るクラス」ということで一旦納得したんだけど、「ファイルやDBに対して保存・復元出来る」って具体的にどういうことなんだろう?
Java のオブジェクトを、後で復元できるような1次元のデータ列に変換することを「シリアライズ(Serialize)」、あるいは「シリアライゼーション(Serialization)」、「直列化」と呼びます。逆に、シリアライズしたデータ列をオブジェクトに変換(復元)することを、「デシリアライズ(Deserialize)」、「デシリアライゼーション(Deserialization)」と呼びます。
インスタンスの状態をファイルに保存したり、ネットワークを介してインスタンスの転送を行ったりする場合は、このシリアライズを利用します。そのとき対象となるオブジェクトには、インタフェースSerializableをimplementsすることとなります。
Javaの“常識”、“非常識” 第3回 - ITアーキテクト [IT Architect]より引用
「Serializable(直列化可能)なクラス」というのは、「オブジェクトのデータをファイルやDBに保存・復元できるようにしてあるクラス」のことで、実際には「オブジェクトを1次元のデータ列に変換(シリアライズ)出来たり、そこからオブジェクトを復元(デシリアライズ)出来るクラス」のことだったんだ。
そして、「Serializable(直列化可能)なクラス」には「serialVersionUID」を書かないといけないらしい、こんな感じで。
private static final long serialVersionUID = 3690197650326049858L;
なんで?なんだこのランダムな数字、どこから来たの?
もう一度リファレンスを参照してみた。
直列化ランタイムは、直列化可能クラスとバージョン番号 (serialVersionUID) を関連付けます。バージョン番号は、直列化復元時に、直列化オブジェクトの送信側と受信側が直列化互換性のあるこのオブジェクトのクラスをロードしたかどうかを検証するために使用されます。受信側が送信側のクラスと serialVersionUID の異なるオブジェクトのクラスをロードした場合、直列化復元の結果は InvalidClassException になります。直列化可能クラスは、独自の serialVersionUID を明示的に宣言できます。このためには、static かつ final の long 型フィールド「serialVersionUID」を宣言します。
Serializable (Java 2 Platform SE 5.0)より引用
同じクラス名なのにserialVersionUIDが違うと、復元(デシリアライズ)した時にInvalidClassExceptionを投げるようだ。
でも「同じクラス名でserialVersionUIDが異なる」というシチュエーションがあんまり思い浮かばない、他の人が同じクラス名で他のクラスを作ってたとか?じゃあ一人で開発してる限りは必要ない?書かなくても良いのか?と思ったら親切な名無しさんが答えてくれてた。
シリアライズしたクラスと、それを復元するクラスで serialVersionUID が違うと復元時に InvalidClassException食らう。
んで、serialVersionUID は設定しないとコンパイラがクラス定義から自動的にデフォルト値を計算するけど、これはコンパイラが違うだけで値が変わる可能性があるので推奨されないって事らしい。
http://mobile.seisyun.net/cgi/read.cgi/pc11/pc11_tech_1135634403/844より引用
なんと簡潔で分かりやすい。
同じ内容がリファレンスにも書いてあるんだけど、こっちの方が分かりやすい。
しかし、デフォルトの serialVersionUID の計算は、クラスの詳細情報に大きく左右され、このクラスの詳細情報はさらに、コンパイラの実装状況に依存しているので、直列化復元時に予期しない InvalidClassException が発生する可能性があります。
このような問題を防ぐためにも、すべての直列化可能クラスがserialVersionUID 値を明示的に宣言するように設定することを強くお勧めします。
Serializable (Java 2 Platform SE 5.0)より引用
なるほど、やっと分かった気がする。
Serializableについて語っていた皆さん、どうもありがとう、助かりました。
改めて「うーん」と考えた(いや考えてない、調べて理解するのに頭を使っただけ)、java.io.Serializableインタフェースってなんだ?
先ずはリファレンスを参照してみた。
クラスの直列化可能性は、java.io.Serializable インタフェースを実装したクラスによって有効になります。このインタフェースを実装していないクラスでは、その状態が直列化または直列化復元されることはありません。直列化可能クラスのサブタイプは、すべてそれ自体が直列化可能です。直列化インタフェースにはメソッドやフィールドはなく、直列化可能であることを識別するためだけに機能します。
Serializable (Java 2 Platform SE 5.0)より引用
「直列化可能」にしてくれるインタフェースらしい。
でも「直列化可能」って何だ!電池でもないのにクラスが直列になるの?
そういえば理科の時間にやった電池の直列、並列も苦手だったな。
長持ちする方を選べとか、豆電球が明るく光る方を選べとか・・・電池を大量に買えばいいから、この問題は解けなくても構わないや、と投げた気がする。
走馬灯のように駆け巡る電池の思い出はさておいて、母語とは思えないほど「直列化可能」という言葉の意味が分からないので、検索、ITアーキテクトで解説を発見。
インタフェースSerializableは、メソッドやフィールドを1つも持たない空のインタフェース(マーカ・インタフェース)です。このインタフェースは、それをimplementsするオブジェクトがシリアライズ可能であることを示すためだけに機能します。
Javaの“常識”、“非常識” 第3回 - ITアーキテクト [IT Architect]より引用
しまった、「直列化可能」が分からないから検索してたのに、もうひとつ「分からない新しい言葉」が出てきた。
シリアライズ可能?これって「直列化可能」と同じ意味?
分からないので訳してみた。
* serializable
【名】
《コ》直列化可能
“Serializable”の検索結果(1 件):英辞郎 on the Web:スペースアルクより引用
全く同じだ。
「Serializable=直列化可能」、ここまでは分かった。
Serializableインタフェースは、名前のとおり「Serializableインタフェースをimplementsしたクラス」が、直列化可能であることを示すためだけに機能する、ということのようです。
でも「Serializable」という言葉の意味も、「直列化可能」という言葉の意味もまだ分からない。
英英辞書か国語辞典かで迷いながら再度検索、よくお世話になるTECHSCOREが引っかかった。
任意のクラスのデータをファイルに保存したり、ファイルから復元したりする事が考えられます。独自に保存・復元のプログラムを記述する事も可能ですが、 Javaでは簡単にこの仕組みを実現できる機能が提供されています。(中略)あるクラスのオブジェクトが保存・復元できる事を、「直列化可能である」と言います。また保存・復元できるかどうかを「直列化可能性」と呼びます。
オブジェクトのシリアライズ入出力-TECHSCORE-より引用
「生成されたオブジェクトのデータを、ファイルやDBに対して保存・復元出来る」
そういうクラスのことを「Serializable(直列化可能)なクラス」と呼ぶらしい。
じゃあAppFuseで自動生成されたModelのクラスたちは、みんな「Serializable(直列化可能)なクラス」だったのか、確かにデータ出し入れしてたものね。
納得しかけたら稚内北星学園大学のJavaBeansに関する資料を見つけた。
Bean は、必要に応じてオブジェクトの状態を保存したり、復元したりすることができなければいけません。このことを、Beanを「永続化」する、といいます。このためには、Beanにjava.io.Serializableインタフェースを実装する必要があります。このインタフェースにはメソッドは定義されていないので、次のように定義するだけで構いません。
2003年度 ソフトウェア特論より引用
「直列化可能」、「Serializable」ときて今度は「永続化」ですか、そうですか、多分同じ意味だよね?
不安になったのでもう少し調べる。
もうひとつ、JavaBeansの仕様では、Java Beanクラスは「直列化可能」である必要がある。
Java Beanクラスは、プロパティに格納した情報を保存できる必要があるため、Serializableインターフェイスの実装クラスとする必要がある。(中略)これは絶対必要な条件ではない。実際、通常のサーブレットとJSPで使用する場合には直列化可能である必要はない。ただし、システムによっては必要不可欠であるため、Serializableインターフェイスの実装クラスとしておいた方が安全だろう。
JavaA2Z【JavaBeansとは】より引用
Modelのクラスたちは、プロパティに格納した情報をDBに渡したり、DBから受け取ったりするための部品(JavaBeans)なので、「Serializable(直列化可能)」でなければいけない、と。
でも、さっき「Serializable(直列化可能)なクラス」というのは、「生成されたオブジェクトのデータを、ファイルやDBに対して保存・復元出来るクラス」ということで一旦納得したんだけど、「ファイルやDBに対して保存・復元出来る」って具体的にどういうことなんだろう?
Java のオブジェクトを、後で復元できるような1次元のデータ列に変換することを「シリアライズ(Serialize)」、あるいは「シリアライゼーション(Serialization)」、「直列化」と呼びます。逆に、シリアライズしたデータ列をオブジェクトに変換(復元)することを、「デシリアライズ(Deserialize)」、「デシリアライゼーション(Deserialization)」と呼びます。
インスタンスの状態をファイルに保存したり、ネットワークを介してインスタンスの転送を行ったりする場合は、このシリアライズを利用します。そのとき対象となるオブジェクトには、インタフェースSerializableをimplementsすることとなります。
Javaの“常識”、“非常識” 第3回 - ITアーキテクト [IT Architect]より引用
「Serializable(直列化可能)なクラス」というのは、「オブジェクトのデータをファイルやDBに保存・復元できるようにしてあるクラス」のことで、実際には「オブジェクトを1次元のデータ列に変換(シリアライズ)出来たり、そこからオブジェクトを復元(デシリアライズ)出来るクラス」のことだったんだ。
そして、「Serializable(直列化可能)なクラス」には「serialVersionUID」を書かないといけないらしい、こんな感じで。
private static final long serialVersionUID = 3690197650326049858L;
なんで?なんだこのランダムな数字、どこから来たの?
もう一度リファレンスを参照してみた。
直列化ランタイムは、直列化可能クラスとバージョン番号 (serialVersionUID) を関連付けます。バージョン番号は、直列化復元時に、直列化オブジェクトの送信側と受信側が直列化互換性のあるこのオブジェクトのクラスをロードしたかどうかを検証するために使用されます。受信側が送信側のクラスと serialVersionUID の異なるオブジェクトのクラスをロードした場合、直列化復元の結果は InvalidClassException になります。直列化可能クラスは、独自の serialVersionUID を明示的に宣言できます。このためには、static かつ final の long 型フィールド「serialVersionUID」を宣言します。
Serializable (Java 2 Platform SE 5.0)より引用
同じクラス名なのにserialVersionUIDが違うと、復元(デシリアライズ)した時にInvalidClassExceptionを投げるようだ。
でも「同じクラス名でserialVersionUIDが異なる」というシチュエーションがあんまり思い浮かばない、他の人が同じクラス名で他のクラスを作ってたとか?じゃあ一人で開発してる限りは必要ない?書かなくても良いのか?と思ったら親切な名無しさんが答えてくれてた。
シリアライズしたクラスと、それを復元するクラスで serialVersionUID が違うと復元時に InvalidClassException食らう。
んで、serialVersionUID は設定しないとコンパイラがクラス定義から自動的にデフォルト値を計算するけど、これはコンパイラが違うだけで値が変わる可能性があるので推奨されないって事らしい。
http://mobile.seisyun.net/cgi/read.cgi/pc11/pc11_tech_1135634403/844より引用
なんと簡潔で分かりやすい。
同じ内容がリファレンスにも書いてあるんだけど、こっちの方が分かりやすい。
しかし、デフォルトの serialVersionUID の計算は、クラスの詳細情報に大きく左右され、このクラスの詳細情報はさらに、コンパイラの実装状況に依存しているので、直列化復元時に予期しない InvalidClassException が発生する可能性があります。
このような問題を防ぐためにも、すべての直列化可能クラスがserialVersionUID 値を明示的に宣言するように設定することを強くお勧めします。
Serializable (Java 2 Platform SE 5.0)より引用
なるほど、やっと分かった気がする。
Serializableについて語っていた皆さん、どうもありがとう、助かりました。

