Вывести внешнюю переменную конечного экземпляра
Вот мой пример кода:
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";
}
}