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

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

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

  • 0
    Не могли бы вы инкапсулировать это поле в классе, а затем создать экземпляр указанного класса при чтении данных? Кроме этого, действительно не имеет смысла повторно инициализировать окончательную переменную экземпляра после того, как экземпляр был создан; вот и весь смысл final
  • 1
    @ VinceEmigh Но в этом случае я не реинициализирую объект. Это экстернализация, поэтому я хочу сохранить объект в файл и восстановить его для дальнейшего использования.
Показать ещё 1 комментарий
Теги:
deserialization
serialization
serializable
externalizable

1 ответ

-1

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

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

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";
  }
}
  • 0
    readExternal() является методом экземпляра и должен возвращать void .
  • 0
    Ах, забыл, что он все еще должен соответствовать заголовкам метода интерфейса. Я удалю этот ответ.
Показать ещё 4 комментария

Ещё вопросы

Сообщество Overcoder
Наверх
Меню