📜  Java中带有继承的对象序列化

📅  最后修改于: 2022-05-13 01:55:40.810000             🧑  作者: Mango

Java中带有继承的对象序列化

先决条件:序列化、继承

序列化是一种将对象的状态转换为字节流的机制。字节数组可以是对象的类、版本和内部状态。

反序列化是使用字节流在内存中重新创建实际Java对象的逆过程。该机制用于持久化对象。

有一些关于继承的序列化案例:

情况1:如果超类是可序列化的,那么子类是自动可序列化的

如果超类是可序列化的,那么默认情况下,每个子类都是可序列化的。因此,即使子类没有实现 Serializable 接口(如果它的超类实现了 Serializable),我们也可以序列化子类对象。

Java
// Java program to demonstrate 
// that if superclass is 
// serializable then subclass 
// is automatically serializable 
  
import java.io.FileInputStream; 
import java.io.FileOutputStream; 
import java.io.ObjectInputStream; 
import java.io.ObjectOutputStream; 
import java.io.Serializable; 
  
// superclass A 
// implementing Serializable interface 
class A implements Serializable 
{ 
    int i; 
      
    // parameterized constructor 
    public A(int i) 
    { 
        this.i = i; 
    } 
      
} 
  
// subclass B 
// B class doesn't implement Serializable 
// interface. 
class B extends A 
{ 
    int j; 
      
    // parameterized constructor 
    public B(int i, int j) 
    { 
        super(i); 
        this.j = j; 
    } 
} 
  
// Driver class 
public class Test 
{ 
    public static void main(String[] args) 
            throws Exception 
    { 
        B b1 = new B(10,20); 
          
        System.out.println("i = " + b1.i); 
        System.out.println("j = " + b1.j); 
          
        /* Serializing B's(subclass) object */
          
        //Saving of object in a file 
        FileOutputStream fos = new FileOutputStream("abc.ser"); 
        ObjectOutputStream oos = new ObjectOutputStream(fos); 
              
        // Method for serialization of B's class object 
        oos.writeObject(b1); 
              
        // closing streams 
        oos.close(); 
        fos.close(); 
              
        System.out.println("Object has been serialized"); 
          
        /* De-Serializing B's(subclass) object */
          
        // Reading the object from a file 
        FileInputStream fis = new FileInputStream("abc.ser"); 
        ObjectInputStream ois = new ObjectInputStream(fis); 
              
        // Method for de-serialization of B's class object 
        B b2 = (B)ois.readObject(); 
              
        // closing streams 
        ois.close(); 
        fis.close(); 
              
        System.out.println("Object has been deserialized"); 
          
        System.out.println("i = " + b2.i); 
        System.out.println("j = " + b2.j); 
    } 
}


Java
// Java program to demonstrate
// the case if superclass need
// not to be serializable
// while serializing subclass
  
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
  
// superclass A
// A class doesn't implement Serializable
// interface.
class A {
    int i;
  
    // parameterized constructor
    public A(int i){ 
      this.i = i; 
    }
  
    // default constructor
    // this constructor must be present
    // otherwise we will get runtime exception
    public A()
    {
        i = 50;
        System.out.println("A's class constructor called");
    }
}
  
// subclass B
// implementing Serializable interface
class B extends A implements Serializable {
    int j;
  
    // parameterized constructor
    public B(int i, int j)
    {
        super(i);
        this.j = j;
    }
}
  
// Driver class
public class Test {
    public static void main(String[] args) throws Exception
    {
        B b1 = new B(10, 20);
  
        System.out.println("i = " + b1.i);
        System.out.println("j = " + b1.j);
  
        // Serializing B's(subclass) object
  
        // Saving of object in a file
        FileOutputStream fos
            = new FileOutputStream("abc.ser");
        ObjectOutputStream oos
            = new ObjectOutputStream(fos);
  
        // Method for serialization of B's class object
        oos.writeObject(b1);
  
        // closing streams
        oos.close();
        fos.close();
  
        System.out.println("Object has been serialized");
  
        // De-Serializing B's(subclass) object
  
        // Reading the object from a file
        FileInputStream fis
            = new FileInputStream("abc.ser");
        ObjectInputStream ois = new ObjectInputStream(fis);
  
        // Method for de-serialization of B's class object
        B b2 = (B)ois.readObject();
  
        // closing streams
        ois.close();
        fis.close();
  
        System.out.println("Object has been deserialized");
  
        System.out.println("i = " + b2.i);
        System.out.println("j = " + b2.j);
    }
}


Java
// Java program to demonstrate 
// how to prevent 
// subclass from serialization 
  
import java.io.FileInputStream; 
import java.io.FileOutputStream; 
import java.io.IOException; 
import java.io.NotSerializableException; 
import java.io.ObjectInputStream; 
import java.io.ObjectOutputStream; 
import java.io.Serializable; 
  
// superclass A 
// implementing Serializable interface 
class A implements Serializable 
{ 
    int i; 
      
    // parameterized constructor 
    public A(int i) 
    { 
        this.i = i; 
    } 
      
} 
  
// subclass B 
// B class doesn't implement Serializable 
// interface. 
class B extends A 
{ 
    int j; 
      
    // parameterized constructor 
    public B(int i,int j) 
    { 
        super(i); 
        this.j = j; 
    } 
      
    // By implementing writeObject method, 
    // we can prevent 
    // subclass from serialization 
    private void writeObject(ObjectOutputStream out) throws IOException 
    { 
        throw new NotSerializableException(); 
    } 
      
    // By implementing readObject method, 
    // we can prevent 
    // subclass from de-serialization 
    private void readObject(ObjectInputStream in) throws IOException 
    { 
        throw new NotSerializableException(); 
    } 
      
} 
  
// Driver class 
public class Test 
{ 
    public static void main(String[] args) 
            throws Exception 
    { 
        B b1 = new B(10, 20); 
          
        System.out.println("i = " + b1.i); 
        System.out.println("j = " + b1.j); 
          
        // Serializing B's(subclass) object 
          
        //Saving of object in a file 
        FileOutputStream fos = new FileOutputStream("abc.ser"); 
        ObjectOutputStream oos = new ObjectOutputStream(fos); 
              
        // Method for serialization of B's class object 
        oos.writeObject(b1); 
              
        // closing streams 
        oos.close(); 
        fos.close(); 
              
        System.out.println("Object has been serialized"); 
          
        // De-Serializing B's(subclass) object 
          
        // Reading the object from a file 
        FileInputStream fis = new FileInputStream("abc.ser"); 
        ObjectInputStream ois = new ObjectInputStream(fis); 
              
        // Method for de-serialization of B's class object 
        B b2 = (B)ois.readObject(); 
              
        // closing streams 
        ois.close(); 
        fis.close(); 
              
        System.out.println("Object has been deserialized"); 
          
        System.out.println("i = " + b2.i); 
        System.out.println("j = " + b2.j); 
    } 
}


输出:

i = 10
j = 20
Object has been serialized
Object has been deserialized
i = 10
j = 20

一种

情况2:如果超类不可序列化,那么子类仍然可以序列化

即使超类没有实现 Serializable 接口,如果子类本身实现了 Serializable 接口,我们也可以序列化子类对象。所以我们可以说要序列化子类对象,超类不需要是可序列化的。但是在这种情况下,在序列化过程中超类的实例会发生什么。以下过程对此进行了说明。

案例 2(a):当一个类是可序列化的,但它的超类不是时会发生什么?

序列化:在序列化时,如果任何实例变量继承自不可序列化的超类,那么 JVM 会忽略该实例变量的原始值并将默认值保存到文件中。

序列化:在反序列化的时候,如果存在任何不可序列化的超类,那么JVM会在超类中执行实例控制流。要在类中执行实例控制流,JVM 将始终调用该类的默认(无参数)构造函数。因此,每个不可序列化的超类都必须包含一个默认构造函数。否则,我们将得到一个运行时异常。

Java

// Java program to demonstrate
// the case if superclass need
// not to be serializable
// while serializing subclass
  
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
  
// superclass A
// A class doesn't implement Serializable
// interface.
class A {
    int i;
  
    // parameterized constructor
    public A(int i){ 
      this.i = i; 
    }
  
    // default constructor
    // this constructor must be present
    // otherwise we will get runtime exception
    public A()
    {
        i = 50;
        System.out.println("A's class constructor called");
    }
}
  
// subclass B
// implementing Serializable interface
class B extends A implements Serializable {
    int j;
  
    // parameterized constructor
    public B(int i, int j)
    {
        super(i);
        this.j = j;
    }
}
  
// Driver class
public class Test {
    public static void main(String[] args) throws Exception
    {
        B b1 = new B(10, 20);
  
        System.out.println("i = " + b1.i);
        System.out.println("j = " + b1.j);
  
        // Serializing B's(subclass) object
  
        // Saving of object in a file
        FileOutputStream fos
            = new FileOutputStream("abc.ser");
        ObjectOutputStream oos
            = new ObjectOutputStream(fos);
  
        // Method for serialization of B's class object
        oos.writeObject(b1);
  
        // closing streams
        oos.close();
        fos.close();
  
        System.out.println("Object has been serialized");
  
        // De-Serializing B's(subclass) object
  
        // Reading the object from a file
        FileInputStream fis
            = new FileInputStream("abc.ser");
        ObjectInputStream ois = new ObjectInputStream(fis);
  
        // Method for de-serialization of B's class object
        B b2 = (B)ois.readObject();
  
        // closing streams
        ois.close();
        fis.close();
  
        System.out.println("Object has been deserialized");
  
        System.out.println("i = " + b2.i);
        System.out.println("j = " + b2.j);
    }
}

输出:

i = 10
j = 20
Object has been serialized
A's class constructor called
Object has been deserialized
i = 50
j = 20

案例3:如果超类是可序列化的,但我们不希望子类被序列化

没有直接的方法可以防止子类在Java中序列化。程序员实现此目的的一种可能方法是在子类中实现writeObject()readObject()方法,并且需要从这些方法中抛出NotSerializableException 。这些方法分别在序列化和反序列化期间执行。通过覆盖这些方法,我们只是在实现我们的自定义序列化。

Java

// Java program to demonstrate 
// how to prevent 
// subclass from serialization 
  
import java.io.FileInputStream; 
import java.io.FileOutputStream; 
import java.io.IOException; 
import java.io.NotSerializableException; 
import java.io.ObjectInputStream; 
import java.io.ObjectOutputStream; 
import java.io.Serializable; 
  
// superclass A 
// implementing Serializable interface 
class A implements Serializable 
{ 
    int i; 
      
    // parameterized constructor 
    public A(int i) 
    { 
        this.i = i; 
    } 
      
} 
  
// subclass B 
// B class doesn't implement Serializable 
// interface. 
class B extends A 
{ 
    int j; 
      
    // parameterized constructor 
    public B(int i,int j) 
    { 
        super(i); 
        this.j = j; 
    } 
      
    // By implementing writeObject method, 
    // we can prevent 
    // subclass from serialization 
    private void writeObject(ObjectOutputStream out) throws IOException 
    { 
        throw new NotSerializableException(); 
    } 
      
    // By implementing readObject method, 
    // we can prevent 
    // subclass from de-serialization 
    private void readObject(ObjectInputStream in) throws IOException 
    { 
        throw new NotSerializableException(); 
    } 
      
} 
  
// Driver class 
public class Test 
{ 
    public static void main(String[] args) 
            throws Exception 
    { 
        B b1 = new B(10, 20); 
          
        System.out.println("i = " + b1.i); 
        System.out.println("j = " + b1.j); 
          
        // Serializing B's(subclass) object 
          
        //Saving of object in a file 
        FileOutputStream fos = new FileOutputStream("abc.ser"); 
        ObjectOutputStream oos = new ObjectOutputStream(fos); 
              
        // Method for serialization of B's class object 
        oos.writeObject(b1); 
              
        // closing streams 
        oos.close(); 
        fos.close(); 
              
        System.out.println("Object has been serialized"); 
          
        // De-Serializing B's(subclass) object 
          
        // Reading the object from a file 
        FileInputStream fis = new FileInputStream("abc.ser"); 
        ObjectInputStream ois = new ObjectInputStream(fis); 
              
        // Method for de-serialization of B's class object 
        B b2 = (B)ois.readObject(); 
              
        // closing streams 
        ois.close(); 
        fis.close(); 
              
        System.out.println("Object has been deserialized"); 
          
        System.out.println("i = " + b2.i); 
        System.out.println("j = " + b2.j); 
    } 
}

输出:

i = 10
j = 20
Exception in thread "main" java.io.NotSerializableException
    at B.writeObject(Test.java:44)