Является ли подкласс класса "Сериализуемый" автоматически "Сериализуемым"?
Я хотел спросить, реализует ли дочерний элемент родителя, который реализует интерфейс 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 в родительском для установки значений по мере необходимости во время де-сериализации, но в противном случае мы будем иметь значения по умолчанию.