Вывести внешнюю переменную конечного экземпляра

Вот мой пример кода:

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, необходимо экстернализировать, в то время как мы также хотим сохранить его неизменность.

Итак, как правильно решить эту проблему?

1 ответ

Функция чтения не имеет большого смысла с идеей конечного поля, потому что какое бы значение оно не было инициализировано, оно должно быть его значением навсегда. Функция чтения не должна быть в состоянии изменить это.

Очевидно, объекты инициализированы с public ExternalizableClass(int i) конструктор не должен быть в состоянии прочитать новое значение - если они могут, то их id значение не совсем окончательное. Единственный другой способ сделать это - заставить конструктор по умолчанию инициализировать "непрочитанный" экземпляр, что позволит позже вызвать read для него. Это, однако, требует удаления окончательного модификатора и обхода этого. Так что это будет выглядеть так:

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";
  }
}
Другие вопросы по тегам