1

ここに私のサンプルコードがあります:

public class ExternalizableClass implements Externalizable
{
  final int id;

  public ExternalizableClass()
  {
    id = 0;
  }

  public ExternalizableClass(int i)
  {
    id = i;
  }

  @Override
  public void writeExternal(ObjectOutput out) throws IOException
  {
    out.writeInt(id);
  }

  @Override
  public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException
  {
    id = in.readInt();
  }

  @Override
  public String toString()
  {
    return "id: " + id;
  }
}

id = in.readInt();を与えるため、コンパイルに失敗しますError:(36, 5) java: cannot assign a value to final variable id。ただし、id などの不変フィールドを外部化する必要がある一方で、その不変性も保持したいという実際の使用例を考えることができます。

では、この問題を解決する正しい方法は何ですか?

4

1 に答える 1

-1

読み取り関数は、最終フィールドの考え方にはあまり意味がありません。初期化された値は、永久にその値である必要があるためです。read 関数はそれを変更できないはずです。

明らかに、コンストラクターで初期化されたオブジェクトpublic ExternalizableClass(int i)は新しい値を読み取れないはずです。読み取れる場合、それらのid値は実際には最終的なものではありません。これを行う唯一の方法は、デフォルトのコンストラクターで「未読」インスタンスを初期化し、後でそのインスタンスで read を呼び出せるようにすることです。ただし、これには final 修飾子を削除してそれを回避する必要があります。したがって、次のようになります。

public class ExternalizableClass implements Externalizable
{
  private int id;
  private boolean initted;

  int getId(){
      return id;
  }

  public ExternalizableClass(int i, boolean initted){
      id = i;
      this.initted = initted;
  }

  public ExternalizableClass(){
      this(0, true); //Default instances can't be changed
  }

  public ExternalizableClass(int i)
  {
    this(i, true); //Instances from this constructor can't be changed either
  }

  @Override
  public void writeExternal(ObjectOutput out) throws RuntimeException, IOException
  {
    if(! initted)
        throw new RuntimeException("Can't write unitialized instance, " + this);
    out.writeInt(id);
  }

  @Override
  public void readExternal(ObjectInput in) throws RuntimeException, IOException, ClassNotFoundException
  {
    if(initted)
        throw new RuntimeException("Can't Read into already initialized object ," + this);
    id = in.readInt();
    initted = true;
  }

  @Override
  public String toString()
  {
    if(initted) return "id: " + id;
    else return "No id";
  }
}
于 2014-12-27T03:58:00.840 に答える