Я хотел спросить, реализует ли дочерний элемент родителя, который реализует интерфейс Serializable, интерфейс Serializable или, другими словами, может быть сериализован этот ребенок?
Является ли подкласс класса "Сериализуемый" автоматически "Сериализуемым"?
Ответ 1
Я хотел спросить, реализует ли потомок родителя, который реализует интерфейс "Сериализуемый", интерфейс "Сериализуемый", или, другими словами, этот потомок может быть сериализован?
Ответ на первую часть - Да. Это является естественным следствием наследования Java.
Ответ на вторую часть не всегда!
Учти это:
public class Parent implements Serializable {
private int i;
// ...
}
public class Child extends Parent {
private final Thread t = new Thread(); // a non-serializable object
// ...
}
Экземпляр Parent
может быть сериализован, но экземпляр Child
не может... потому что у него есть атрибут, тип которого (Thread
) не сериализуем.
(Теперь, если t
был объявлен как transient
, или если Child
избегал использования механизма сериализации по умолчанию, Child
мог бы быть сериализуемым. Но я хочу сказать, что сериализуемость является эмерджентным свойством, а не наследуемым свойством.)
Ответ 2
Да. Если родитель реализует Serializable
, то любые дочерние классы также Serializable
.
static class A implements Serializable {
}
static class B extends A {
}
public static void main(String[] args) {
Serializable b = new B(); // <-- this is a legal statement.
}
B
также реализует Serializable
.
Ответ 3
Краткий ответ: Да, если родительский класс сериализован, то дочерний класс автоматически сериализуется.
Длинный ответ:
-
Если Родительский класс является Сериализуемым, то дочерний класс по умолчанию Сериализуем. JVM проверяет, реализует ли родительский класс Serializable, и если да, то также считает, что дочерний класс также сериализуем. Следовательно, Сериализация является наследуемым понятием, которое приходит от родителя к ребенку.
открытый класс ParentSerializableNotChild {
public static void main(String[] args) throws Exception{ Child chileSerialize = new Child(); //Serialization FileOutputStream fos = new FileOutputStream("test.ser"); ObjectOutputStream oos = new ObjectOutputStream(fos); oos.writeObject(chileSerialize); FileInputStream fis = new FileInputStream("test.ser"); ObjectInputStream ois = new ObjectInputStream(fis); Child childDeserialize = (Child) ois.readObject(); System.out.println(childDeserialize.i + "---" + childDeserialize.j); //10---20 } } class Parent implements Serializable{ int i = 10; } class Child extends Parent{ int j = 20; }
-
Если родительский класс не сериализуем, то и дочерний класс может быть сериализован. Наилучшим примером этого является класс Object, класс Object не реализует Serializable, но любой класс, являющийся дочерним по отношению к классу Object, может реализовать Serializable.
открытый класс ChildSerializedParentNot {
public static void main(String[] args) throws Exception{ Dogy d = new Dogy(); d.i = 888; d.j = 999; FileOutputStream fos = new FileOutputStream("inheritance.ser"); ObjectOutputStream oos = new ObjectOutputStream(fos); System.out.println("Serializing"); oos.writeObject(d); FileInputStream fis = new FileInputStream("inheritance.ser"); ObjectInputStream ois = new ObjectInputStream(fis); System.out.println("Deserializing"); Dogy d2 = (Dogy) ois.readObject(); System.out.println(d2.i + "-----" + d2.j); } } class Animal{ int i = 10; Animal(){ System.out.println("Parent class cons"); } } class Dogy extends Animal implements Serializable{ Dogy(){ System.out.println("Child class constructor"); } int j = 20; }
Выход:
Родительский класс минусы
Конструктор дочернего класса
Сериализация
десериализации
Родительский класс минусы
10 999 -----
Сверху, есть 3 случая, когда ребенок сериализуется, но не является родителем.
Случай 1: во время сериализации JVM проверяет, поступает ли какая-либо переменная экземпляра из не сериализованного родительского класса. Если это так, то родительский класс не сериализуем и его переменная экземпляра участвует в сериализации, тогда jvm игнорирует значение переменной экземпляра и сохраняет значение по умолчанию в файле. (В приведенном выше примере, я хранится как 0 в файле).
Случай 2: во время десериализации JVM проверяет, поступает ли какая-либо переменная экземпляра из не сериализованного родительского класса. Если это так, JVM запустит INSTANCE CONTROL FLOW, и первоначальное значение объекта будет восстановлено.
ПОТОК КОНТРОЛЯ ИНСТАНЦИИ (короче) http://java2bigdata.blogspot.in/2015/05/instance-control-flow-in-java.html:
1. Идентификация члена инстанции.
2. Выполнение назначения и создания экземпляра переменной экземпляра.
3. Исполнение конструктора.
Случай 3: Поскольку в потоке управления экземпляра выполняется конструктор. Следовательно, в случае не сериализованного родителя вызывается конструктор без аргументов, этот конструктор может быть предоставлен пользователем или создан jvm. Если нет конструктора без аргументов, это приведет к InvalidClassException.
Ответ 4
Нам не нужен конструктор no-arg, а родительский сериализуем.
Но когда дочерний объект сериализуется, а не родительский, мы должны иметь no-arg const в родительском для установки значений по мере необходимости во время де-сериализации, но в противном случае мы будем иметь значения по умолчанию.