Здесь мой пример кода:
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, должно быть экстернализировано, в то время как мы также хотим сохранить его неизменность.
Итак, какой правильный способ решить эту проблему?
Функция чтения не имеет большого смысла в идее конечного поля, потому что любое значение, которое оно было инициализировано, должно быть его значением навсегда. Функция чтения не должна его изменять.
Очевидно, что объекты, инициализированные 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";
}
}
readExternal()
является методом экземпляра и должен возвращать void
.
final