Serialización de objetos con herencia en Java

Requisito previo: serialización , herencia

La serialización es un mecanismo para convertir el estado de un objeto en un flujo de bytes. La array de bytes puede ser la clase, la versión y el estado interno del objeto.

La deserialización es el proceso inverso en el que se utiliza el flujo de bytes para recrear el objeto Java real en la memoria. Este mecanismo se utiliza para persistir el objeto.

Existen algunos casos de Serialización con respecto a la herencia:

Caso 1: si la superclase es serializable, entonces la subclase es serializable automáticamente

Si la superclase es Serializable, entonces, por defecto, cada subclase es serializable. Por lo tanto, aunque la subclase no implemente la interfaz Serializable (y si su superclase implementa Serializable), entonces podemos serializar el objeto de la subclase. 

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); 
    } 
}

Producción: 

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

a

Caso 2: si una superclase no es serializable, entonces la subclase aún puede serializarse 

Aunque la superclase no implementa una interfaz Serializable, podemos serializar objetos de subclase si la subclase misma implementa una interfaz Serializable. Entonces podemos decir que para serializar objetos de subclase, la superclase no necesita ser serializable. Pero, ¿qué sucede con las instancias de la superclase durante la serialización en este caso? El siguiente procedimiento explica esto.

Caso 2(a): ¿Qué sucede cuando una clase es serializable, pero su superclase no lo es?

Serialización: en el momento de la serialización, si alguna variable de instancia hereda de la superclase no serializable, JVM ignora el valor original de esa variable de instancia y guarda el valor predeterminado en el archivo.

Deserialización: en el momento de la deserialización, si está presente alguna superclase no serializable, JVM ejecutará el flujo de control de instancia en la superclase. Para ejecutar el flujo de control de instancias en una clase, JVM siempre invocará el constructor predeterminado (sin argumentos) de esa clase. Entonces, cada superclase no serializable debe contener necesariamente un constructor predeterminado. De lo contrario, obtendremos una excepción de tiempo de ejecución.

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);
    }
}

Producción: 

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

Caso 3: Si la superclase es serializable, pero no queremos que la subclase sea serializada

No hay una forma directa de evitar que la subclase se serialice en java. Una forma posible en la que un programador puede lograr esto es implementando los métodos writeObject() y readObject() en la subclase y necesita lanzar NotSerializableException desde estos métodos. Estos métodos se ejecutan durante la serialización y la deserialización, respectivamente. Al anular estos métodos, solo estamos implementando nuestra serialización personalizada.

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); 
    } 
}

Producción: 

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

Este artículo es una contribución de Gaurav Miglani . Si te gusta GeeksforGeeks y te gustaría contribuir, también puedes escribir un artículo usando write.geeksforgeeks.org o enviar tu artículo por correo a review-team@geeksforgeeks.org. Vea su artículo que aparece en la página principal de GeeksforGeeks y ayude a otros Geeks.

Escriba comentarios si encuentra algo incorrecto o si desea compartir más información sobre el tema tratado anteriormente.

Publicación traducida automáticamente

Artículo escrito por GeeksforGeeks-1 y traducido por Barcelona Geeks. The original can be accessed here. Licence: CCBY-SA

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *