Сериализация и наследование объектов Java - PullRequest
31 голосов
/ 26 декабря 2011

Скажем, у вас есть эти два класса, 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. Так что же происходит, когда bar сериализуется?

    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». Вопрос в том, почему конструктор по умолчанию вызывается, когда класс не сериализован?

Ответы [ 3 ]

22 голосов
/ 26 декабря 2011

Serializable - это просто «интерфейс маркера» для данного класса.

Но этот класс должен придерживаться определенных правил:

http://docs.oracle.com/javase/1.5.0/docs/api/java/io/Serializable.html

Дляразрешить сериализацию подтипов несериализуемых классов, подтип может взять на себя ответственность за сохранение и восстановление состояния открытых, защищенных и (если доступно) полей супертипа.Подтип может принять на себя эту ответственность, только если расширяемый класс имеет доступный конструктор без аргументов для инициализации состояния класса.Ошибочно объявлять класс Serializable, если это не так.

, чтобы ответить на вопрос @Sleiman Jneidi, заданный в комментарии, в документации оракула, упомянутой выше, четко указан

Во время десериализации поля несериализуемых классов будут инициализированы с использованием открытого или защищенного конструктора класса без аргументов класса.Конструктор без аргументов должен быть доступен для подкласса, который сериализуем.Поля сериализуемых подклассов будут восстановлены из потока.

Таким образом, вызываемый по умолчанию конструктор без аргументов класса Foo вызвал инициализацию.

4 голосов
/ 07 августа 2013

Возможно, defaultWriteObject может записывать только нестатические и непереходные поля текущего класса . Если суперкласс не реализует интерфейс Serializable, поля в суперклассе не могут быть сериализованы в поток.

0 голосов
/ 25 декабря 2013

На самом деле, когда вы будете читать объект родительского класса обратно, так как он не сериализуется вообще ... так что для несериализованных вещей снова JVM проходит тот же процесс, что и при создании нового объекта с использованием нового ключевого слова.

...