- PR -

eclipseで出た警告について

1
投稿者投稿内容
しん
常連さん
会議室デビュー日: 2004/04/04
投稿数: 48
投稿日時: 2007-01-23 02:29
eclipseで下記のように独自の例外を作成したら
「シリアライズ可能クラス、MyException は long型の static final
serialVersionUIDフィールドを宣言していません。」と警告が出てしまいました。
ですからlong型の「serialVersionUID」を加えて警告が出るのを抑えましたが
何のことだろうと思い調べてみると
「送り側と受け側で同じクラスかどうか判別するための値で、宣言しなくても実行時に
自動で計算するけど、InvalidClassExceptionが起こることがあるからなるべく
宣言してね」ということらしいです。
ここで疑問なのですがこの送り側と受け側というのはどういうことでしょうか。
独自の例外を作成しただけで別に何も送ったり受けたりするつもりはないのですが・・・・
「送り側と受け側で同じクラスかどうか判別するための値」ともありますが
送り側と受け側で同じクラスかどうかなんていう判断が必要になる状況が
想像できないのですが・・・
もし何かを送るような処理をするときはこのプロパティに自分で値を入れること
はあるのでしょうか?

コード:

public class MyException extends Exception {
private static final long serialVersionUID = 1L;

public MyException() {
super();
}
}



[ メッセージ編集済み 編集者: かんたろう 編集日時 2007-01-23 02:33 ]
かつのり
ぬし
会議室デビュー日: 2004/03/18
投稿数: 2015
お住まい・勤務地: 札幌
投稿日時: 2007-01-23 03:10
まず、Serializableの仕組みから。
---------------------------------------------------------------------
Serializableを実装したクラスは直列化ができます。
直列化とはインスタンスをバイトの配列にすることです。

バイトの配列ですからファイルに保存することもできるわけです。
そしてロードするときには別の実行環境でロードすることもできるわけです。

例えば、
1.VM1でxx.yy.ZZZと言うクラスのインスタンスを直列化してDBに保存
2.VM2でDBから読み込み
3.VM2で復元
という処理を行ったときに、VM2ではクラスの解決を行います。

VM2インスタンスを復元するわけですから、その前にクラスの解決を行うのは必要です。
VM2にもたまたまxx.yy.ZZZというクラスがあったとしても、
そのクラスがVM1のクラスと同一であると言う保障はありません。

(VM1とVM2のそれぞれのxx.yy.ZZZで同一のSerialVersionUIDを
宣言したからといって同じクラスという保障があるわけではありませんが)

そこで同一のメンバを持っていてserialVersionUIDが同じなら
同じクラスだろうとみなして、インスタンスの復元を行います。
逆に違うなら、何かしらの相違があるに違いないとして、
インスタンスの復元を中止します。
---------------------------------------------------------------------
なぜ、serialVersionUIDが必要かは理解できましたか?

で、なぜ独自の例外でserialVersionUIDを求められたのか。
それは、java.lang.ThrowableがSerializableを実装しているからです。
当然サブクラスも自動的に直列化の対象となる為、
serialVersionUIDが求められたわけです。

serialVersionUIDはユーザがプログラムで操作するものではありません。
ObjectOutputStream/ObjectInputStreamの中で参照されるだけのものです。
nagise
ぬし
会議室デビュー日: 2006/05/19
投稿数: 1141
投稿日時: 2007-01-23 12:28
かんたろう氏の使用しているEclipseのバージョンが不明ですが、
コンパイラのエラー/警告の設定で無視させることもできるはずです。

かつのり氏が詳しく解説してくださっていますが、
VM間で直列化したオブジェクトを受け渡したり、
ファイルに保存して復元したりということをしていないならば
警告しない設定にしてしまってもよいのではないでしょうか。

原理をよく理解したうえで判断してください。

# 考えなしに安直に無視、というのはよくないですね。
かつのり
ぬし
会議室デビュー日: 2004/03/18
投稿数: 2015
お住まい・勤務地: 札幌
投稿日時: 2007-01-23 13:11
nagiseさんの補足ですが、

JDK5.0以降ならアノテーションの@SuppressWarningsに"serial"を指定すると、
クラス単位での警告の抑制が可能です。

これはコンパイラの実装次第なので、
対応していないコンパイラでは無視されます。
Eclipseなら問題なく抑制が可能です。

ちなみにOSSの某プロダクトのコードを見ると、殆どのSerializableなクラスは
private static final long serialVersionUID = 1L;
で統一されていました。
原理を理解しているなら、こういう割り切りもありですね。
nagise
ぬし
会議室デビュー日: 2006/05/19
投稿数: 1141
投稿日時: 2007-01-23 14:27
引用:

かつのりさんの書き込み (2007-01-23 13:11) より:
ちなみにOSSの某プロダクトのコードを見ると、殆どのSerializableなクラスは
private static final long serialVersionUID = 1L;
で統一されていました。
原理を理解しているなら、こういう割り切りもありですね。



このあたりは、私も仕事仲間の人と議論したことがありまして、

バージョンが変わった≠互換性がない

ではないか、という話をしていました。
メソッドに修正が入っても直列化対象となるデータに変更がない場合、
互換性はあるわけで、それを弾くべきか、否かということなのですが、
現実的には管理上手に負えないのでリリースバージョンごとに番号を振るか、
たとえコンパイル結果に影響しなかろうとソースに手が入った時点で
ハッシュ値で振りなおすという運用でもないと運用がまわらないだろう、
ということでした。

クライアント側とサーバ側のプログラムが別になっているケースでは、
サーバ側で該当クラスのバージョン番号が変わると、そのためだけに
クライアントを再配布する必要が出ますが、通信用オブジェクトがあくまでも
通信専用となっていれば、通信用クラスが変わるときは
なんらかの修正がクライアントにもされるはずだから再配布する方向でよかろう、
という判断でしたね。

このあたりは運用の前提などによって判断が分かれるところだと思います。
しん
常連さん
会議室デビュー日: 2004/04/04
投稿数: 48
投稿日時: 2007-01-24 07:25
皆様お返事ありがとうございます。
eclipseの設定で警告が出ないように
することにしました。
1

スキルアップ/キャリアアップ(JOB@IT)