Объект Java Сериализация и наследование
Скажем, у вас есть эти два класса: Foo и Bar, где Bar расширяет Foo и реализует Serializable
class Foo {
public String name;
public Foo() {
this.name = "Default";
}
public Foo(String name) {
this.name = name;
}
}
class Bar extends Foo implements java.io.Serializable {
public int id;
public Bar(String name, int id) {
super(name);
this.id = id;
}
}
Обратите внимание, что Foo не реализует Serializable
. Итак, что происходит, когда штрих сериализуется?
public static void main(String[] args) throws Exception {
FileOutputStream fStream=new FileOutputStream("objects.dat");
ObjectOutputStream oStream=new ObjectOutputStream(fStream);
Bar bar=new Bar("myName",21);
oStream.writeObject(bar);
FileInputStream ifstream = new FileInputStream("objects.dat");
ObjectInputStream istream = new ObjectInputStream(ifstream);
Bar bar1 = (Bar) istream.readObject();
System.out.println(bar1.name + " " + bar1.id);
}
он печатает "По умолчанию 21".
Вопрос в том, почему конструктор по умолчанию вызывается, когда класс не сериализуется?
Ответы
Ответ 1
Serializable - это просто "интерфейс маркера" для данного класса.
Но этот класс должен придерживаться определенных правил:
http://docs.oracle.com/javase/1.5.0/docs/api/java/io/Serializable.html
Чтобы разрешить сериализацию подтипов классов, не связанных с сериализацией, подтип может взять на себя ответственность за сохранение и восстановление государства общедоступного, защищенного и (если доступно) пакета супертипа поля. Подтип может взять на себя эту ответственность, только если класс он расширяет, имеет доступный конструктор no-arg для инициализации класса. Ошибка объявить класс Serializable, если это это не так.
чтобы ответить на вопрос @Sleiman Jneidi, заданный в комментарии,
в упомянутой выше документации оракула, ее четко указано
Во время десериализации поля классов, не связанных с сериализацией, будут инициализированы с использованием открытого или защищенного конструктора no-arg класса. Конструктор no-arg должен быть доступен для подкласса, который является сериализуемым. Поля сериализуемых подклассов будут восстановлены из потока.
Таким образом, конструктор по умолчанию no-arg класса Foo, вызванный, привел к инициализации.
Ответ 2
может быть, что defaultWriteObject может записывать нестатические и непереходные поля текущего класса. Когда суперкласс не реализует интерфейс Serializable, поля в суперклассе не могут быть сериализованы в поток.
Ответ 3
На самом деле, когда вы будете читать объект родительского класса, так как он вообще не сериализуется. Поэтому для несериализации вещей снова JVM проходит тот же процесс, что и он, когда мы создаем новый объект с использованием нового ключевого слова.