When a parent class implements the Serializable interface, its subclasses will be automatically serialized.
The following verifies this:
package Serial;
import ;
public class SuperC implements Serializable {//The parent class implements serialization
int supervalue;
public SuperC(int supervalue) {
= supervalue;
}
public String toString() {
return "supervalue: "+supervalue;
}
}
public class SubC extends SuperC {//Subclasses
int subvalue;
public SubC(int supervalue,int subvalue) {
super(supervalue);
=subvalue;
}
public String toString() {
return ()+" sub: "+subvalue;
}
}
public class Test1 {
public static void main(String [] args){
SubC subc=new SubC(100,200);
FileInputStream in=null;
FileOutputStream out=null;
ObjectInputStream oin=null;
ObjectOutputStream oout=null;
try {
out = new FileOutputStream("");//Subclass serialization
oout = new ObjectOutputStream(out);
(subc);
();
oout=null;
in = new FileInputStream("");
oin = new ObjectInputStream(in);
SubC subc2=(SubC)();//Subclass deserialization
(subc2);
} catch (Exception ex){
();
} finally{
…Omitted here
}
}
}
The operation results are as follows:
supervalue: 100 sub: 200
It can be seen that the subclass has been successfully serialized/deserialized.
How to make subclasses implement serialization seem like a very simple thing, but sometimes, we often cannot let the parent class implement the Serializable interface because sometimes the parent class is abstract (it doesn't matter), and the parent class cannot force each child class to have the ability to serialize. In other words, the purpose of parent class design is only to be inherited.
To write a subclass that can be serialized for a parent class that does not implement the Serializable interface, it is a cumbersome thing to do. It is mentioned in java docs:
“To allow subtypes of non-serializable classes to be serialized, the subtype may assume responsibility for saving and restoring the state of the supertype's public, protected, and (if accessible) package fields. The subtype may assume this responsibility only if the class it extends has an accessible no-arg constructor to initialize the class's state. It is an error to declare a class Serializable if this is not the case. The error will be detected at runtime. ”
In other words, to write a subclass that can be serialized for a parent class that does not implement the Serializable interface:
First, the parent class must have a constructor without parameters;
Second, the subclass is responsible for serializing (deserializing) the domain of the parent class.
We remove the Serializable interface of SuperC and add the Serializable interface to SubC. An error occurred after running:
: Unresolved compilation problem:
Serializable cannot be resolved or is not a valid superinterface
at .(:15)
at Serial.(:19)
Exception in thread "main"
As mentioned in the docs, it is not possible for the parent class to lack a parameterless constructor.
Next, we rewrite this example as suggested in the docs:
public abstract class SuperC {
int supervalue;
public SuperC(int supervalue) {
= supervalue;
}
public SuperC(){}//Add a constructor without parameters
public String toString() {
return "supervalue: "+supervalue;
}
}
public class SubC extends SuperC implements Serializable {
int subvalue;
public SubC(int supervalue,int subvalue) {
super(supervalue);
=subvalue;
}
public String toString() {
return ()+" sub: "+subvalue;
}
private void writeObject( out)
throws IOException{
();//Serialize the object first
(supervalue);//Serialize the domain of the parent class again
}
private void readObject( in)
throws IOException, ClassNotFoundException{
();//Deserialize the object first
supervalue=();//Deserialize the domain of the parent class again
}
}
The results of the operation prove that this method is correct. Here we use the writeObject/readObject method. If this method exists, it will be called during serialization to replace the default behavior (I will discuss it later, let's learn so much first). When serializing, we first call the defaultWriteObject of ObjectOutputStream, which uses the default serialization behavior and then serializes the domain of the parent class; the same is true when deserializing.
To summarize:
Purpose Behavior
For a parent class that implements the Serializable interface, write a subclass that can be serialized. The subclass will automatically implement serialization.
For a parent class that does not implement the Serializable interface, write a subclass that can be serialized. 1. The parent class must have a constructor without parameters; 2. The subclass must first serialize itself, and then the subclass must be responsible for serializing the domain of the parent class.
The following verifies this:
package Serial;
import ;
public class SuperC implements Serializable {//The parent class implements serialization
int supervalue;
public SuperC(int supervalue) {
= supervalue;
}
public String toString() {
return "supervalue: "+supervalue;
}
}
public class SubC extends SuperC {//Subclasses
int subvalue;
public SubC(int supervalue,int subvalue) {
super(supervalue);
=subvalue;
}
public String toString() {
return ()+" sub: "+subvalue;
}
}
public class Test1 {
public static void main(String [] args){
SubC subc=new SubC(100,200);
FileInputStream in=null;
FileOutputStream out=null;
ObjectInputStream oin=null;
ObjectOutputStream oout=null;
try {
out = new FileOutputStream("");//Subclass serialization
oout = new ObjectOutputStream(out);
(subc);
();
oout=null;
in = new FileInputStream("");
oin = new ObjectInputStream(in);
SubC subc2=(SubC)();//Subclass deserialization
(subc2);
} catch (Exception ex){
();
} finally{
…Omitted here
}
}
}
The operation results are as follows:
supervalue: 100 sub: 200
It can be seen that the subclass has been successfully serialized/deserialized.
How to make subclasses implement serialization seem like a very simple thing, but sometimes, we often cannot let the parent class implement the Serializable interface because sometimes the parent class is abstract (it doesn't matter), and the parent class cannot force each child class to have the ability to serialize. In other words, the purpose of parent class design is only to be inherited.
To write a subclass that can be serialized for a parent class that does not implement the Serializable interface, it is a cumbersome thing to do. It is mentioned in java docs:
“To allow subtypes of non-serializable classes to be serialized, the subtype may assume responsibility for saving and restoring the state of the supertype's public, protected, and (if accessible) package fields. The subtype may assume this responsibility only if the class it extends has an accessible no-arg constructor to initialize the class's state. It is an error to declare a class Serializable if this is not the case. The error will be detected at runtime. ”
In other words, to write a subclass that can be serialized for a parent class that does not implement the Serializable interface:
First, the parent class must have a constructor without parameters;
Second, the subclass is responsible for serializing (deserializing) the domain of the parent class.
We remove the Serializable interface of SuperC and add the Serializable interface to SubC. An error occurred after running:
: Unresolved compilation problem:
Serializable cannot be resolved or is not a valid superinterface
at .
at Serial.(:19)
Exception in thread "main"
As mentioned in the docs, it is not possible for the parent class to lack a parameterless constructor.
Next, we rewrite this example as suggested in the docs:
public abstract class SuperC {
int supervalue;
public SuperC(int supervalue) {
= supervalue;
}
public SuperC(){}//Add a constructor without parameters
public String toString() {
return "supervalue: "+supervalue;
}
}
public class SubC extends SuperC implements Serializable {
int subvalue;
public SubC(int supervalue,int subvalue) {
super(supervalue);
=subvalue;
}
public String toString() {
return ()+" sub: "+subvalue;
}
private void writeObject( out)
throws IOException{
();//Serialize the object first
(supervalue);//Serialize the domain of the parent class again
}
private void readObject( in)
throws IOException, ClassNotFoundException{
();//Deserialize the object first
supervalue=();//Deserialize the domain of the parent class again
}
}
The results of the operation prove that this method is correct. Here we use the writeObject/readObject method. If this method exists, it will be called during serialization to replace the default behavior (I will discuss it later, let's learn so much first). When serializing, we first call the defaultWriteObject of ObjectOutputStream, which uses the default serialization behavior and then serializes the domain of the parent class; the same is true when deserializing.
To summarize:
Purpose Behavior
For a parent class that implements the Serializable interface, write a subclass that can be serialized. The subclass will automatically implement serialization.
For a parent class that does not implement the Serializable interface, write a subclass that can be serialized. 1. The parent class must have a constructor without parameters; 2. The subclass must first serialize itself, and then the subclass must be responsible for serializing the domain of the parent class.