Сериализация и наследование объектов 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. Итак, что происходит при сериализации 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 ответов


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

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

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

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

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

во время десериализации поля несериализуемых классов будут инициализированы с использованием public или protected конструктор no-arg класса. Конструктор no-arg должен быть доступен для подкласса, который является сериализуемым. Поля сериализуемых подклассов будут восстановлены из потока.

таким образом, по умолчанию конструктор no-arg класса Foo вызывается, что привело к инициализации.


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


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