web-dev-qa-db-ja.com

@SuppressWarnings( "シリアル")

少し混乱しているので、質問があります(または、明白なことに気づいていない可能性があります)。次のように定義された多数の静的フィールドを含む多くのクラスを含むいくつかのソースコードがあるとします。

_public final class ConverterTYPE  {
    private final static HashMap<String, Byte> STRING_MAP = new HashMap<String, Byte>() {
        {
            put("A", new Byte((byte)12));
            put("B", new Byte((byte)13));
        }
    };

}
_

ご存じのとおり、静的フィールドはシリアル化されません。

しかし、Java(およびEclipse))は、「直列化可能クラスはlong型の静的なfinal serialVersionUIDフィールドを宣言していません」と不平を言っています。

そして次の質問:このような警告をすべて取り除くために@SuppressWarnings("serial")を使用することは、この問題の正しい解決策でしょうか?

編集:

私のクラスはいずれもSerializableインターフェースを実装していません(またはそのスーパークラスを実装していません)。そして、Eclipseは警告とともに_HashMap<String, Byte>_を指しています。それが静的フィールドであることを検出しないのはなぜですか?

18
Lukasz

そのフィールドがシリアル化されない可能性があるからといって、それが参照するもの自体がシリアル化されることは決してありません!他の誰か/何かがそのマップへの参照を取得してそれを直接シリアル化しようとしたり、シリアル化可能なクラスのインスタンスメンバーとして使用したりすることができます。またはインスタンスメンバーに設定することは、コンパイラーの範囲を超えています(とにかくリフレクションでは不可能です)。

考えられる解決策の1つは、イニシャライザスタイルの匿名サブクラスをすべて一緒に回避し、これを行うことです。

private final static HashMap<String, Byte> STRING_MAP = new HashMap<String, Byte>();

static {  
  STRING_MAP.put("A", new Byte((byte)12));
  STRING_MAP.put("B", new Byte((byte)13));
}

ほとんどの場合、結果はほぼ同じになり、コードに匿名クラスが追加されることはありません。

23
Affe

しかし、Java(およびEclipse))は、「直列化可能クラスはlong型の静的なfinal serialVersionUIDフィールドを宣言していません」と不平を言っています。

エラーメッセージと、クラスに最後の静的メンバー変数があるという事実(少なくとも、それが私があなたの説明を解釈する方法です)は、互いに何の関係もありません。

クラスがインターフェイスSerializableを実装するか、クラスのスーパークラスの1つがそれを行います。したがって、コンパイラはクラスがシリアル化可能であることを認識します。シリアライズ可能なクラスには、serialVersionUIDという静的なfinalフィールドが必要です。これは、クラスのインスタンスをシリアライズするときにバージョン管理に使用されます。

注釈@SuppressWarnings("serial")を使用すると、コンパイラーは、欠落しているserialVersionUIDについてシャットダウンします。したがって、はい、それを使用して警告メッセージを取り除くことができますが、シリアル化するつもりがない場合は、クラスにSerializableを(直接的または間接的に)実装させないことをお勧めします。

20
Jesper