简体   繁体   English

外部化最终实例变量

[英]Externalize a final instance variable

Here's my sample code: 这是我的示例代码:

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;
  }
}

It fails to compile because id = in.readInt(); 它无法编译,因为id = in.readInt(); gives Error:(36, 5) java: cannot assign a value to final variable id . 给出Error:(36, 5) java: cannot assign a value to final variable id However, I can think of real use cases where an immutable field, such as id, needs to be externalized, while we also want to preserve its immutability. 但是,我可以想到实际用例,其中需要将不可变字段(例如id)外部化,同时我们还希望保留其不可变性。

So what's the correct way to resolve this issue? 那么解决此问题的正确方法是什么?

The read function doesn't make much sense with the idea of a final field, because whatever value it was initialized to should be its value, forever. read函数对于final字段的概念没有多大意义,因为初始化它的任何值应该永远是它的值。 The read function shouldn't be able to change it. 读取功能不能更改它。

Clearly objects initialized with the public ExternalizableClass(int i) constructor shouldn't be able to read a new value - if they can then their id value isn't really final. 显然,使用public ExternalizableClass(int i)构造函数初始化的对象不应读取新值-如果可以,则其id值并不是真正的最终值。 The only other way I could see doing this is making the default constructor initialize an "unread" instance, allowing you to call read on it later. 我能看到的唯一另一种方法是使默认构造函数初始化一个“未读”实例,从而允许您稍后调用它。 This does, however, require removing the final modifier and working around that. 但是,这确实需要删除最终修饰符并加以解决。 So that would look like this: 这样看起来像这样:

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";
  }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM