Serialización de Java

La serialización de Java es un proceso que convierte objetos en flujos de bytes, de modo que los objetos puedan guardarse en el disco, transmitirse a través de la red o almacenarse en memoria, y más tarde deserializarse para volver a convertir el flujo de bytes en objetos.

La serialización en Java se realiza mediante lajava.io.Serializableinterfaz, que no tiene ningún método, solo es una interfaz de marcado, utilizada para indicar que una clase puede ser serializada.

Cuando serializas un objeto, lo envuelves en un archivo especial que puede guardarse, transmitirse o almacenarse. La deserialización consiste en abrir ese archivo, leer los datos serializados y luego restaurarlos a un objeto para usarlo en el programa.

La serialización es un método para guardar, transmitir y restaurar objetos; permite que los objetos se muevan y compartan entre diferentes computadoras, lo cual es muy útil para sistemas distribuidos, almacenamiento de datos y comunicación multiplataforma.

A continuación se presentan los conceptos básicos y usos de la serialización en Java:

Implementar la interfaz Serializable: para que una clase sea serializable, debe implementar la interfaz java.io.Serializable, lo que le indica al compilador de Java que esta clase puede ser serializada, por ejemplo:

Ejemplo

import java.io.Serializable;

public class MyClass implements Serializable {
    // miembros y métodos de la clase
}

Serializar objeto:Usa la clase ObjectOutputStream para serializar el objeto en un flujo de bytes. A continuación, un ejemplo sencillo:

Ejemplo

MyClass obj = new MyClass();
try {
    FileOutputStream fileOut = new FileOutputStream("object.ser");
    ObjectOutputStream out = new ObjectOutputStream(fileOut);
    out.writeObject(obj);
    out.close();
    fileOut.close();
} catch (IOException e) {
    e.printStackTrace();
}

El código anterior serializa el objeto obj en un archivo llamado "object.ser".

Deserializar objeto:Usa la clase ObjectInputStream para deserializar objetos desde un flujo de bytes. A continuación, un ejemplo sencillo:

Ejemplo

MyClass obj = null;
try {
    FileInputStream fileIn = new FileInputStream("object.ser");
    ObjectInputStream in = new ObjectInputStream(fileIn);
    obj = (MyClass) in.readObject();
    in.close();
    fileIn.close();
} catch (IOException e) {
    e.printStackTrace();
} catch (ClassNotFoundException e) {
    e.printStackTrace();
}

El código anterior lee el flujo de bytes del archivo "object.ser" y lo deserializa en un objeto MyClass.

Las clases ObjectInputStream y ObjectOutputStream son flujos de datos de alto nivel que contienen métodos para deserializar y serializar objetos.

La clase ObjectOutputStream contiene muchos métodos de escritura para escribir varios tipos de datos, pero hay un método especial:

public final void writeObject(Object x) throws IOException

El método anterior serializa un objeto y lo envía al flujo de salida. De manera similar, la clase ObjectInputStream contiene un método para deserializar un objeto como el siguiente:

public final Object readObject() throws IOException, ClassNotFoundException

Este método toma el siguiente objeto del flujo y lo deserializa. Su valor de retorno es Object, por lo tanto, debes convertirlo al tipo de datos adecuado.

Ejemplo

Para demostrar cómo funciona la serialización en Java, usaré la clase Employee mencionada en tutoriales anteriores. Supongamos que definimos la clase Employee como se muestra a continuación, la cual implementa la interfaz Serializable.

Código del archivo Employee.java:

public class Employee implements java.io.Serializable { public String name; public String address; public transient int SSN; public int number; public void mailCheck() { System.out.println("Mailing a check to " + name + " " + address); } }

Ten en cuenta que, para que el objeto de una clase se serialice correctamente, debe cumplir dos condiciones:

La clase debe implementar la interfaz java.io.Serializable.

Todos los atributos de la clase deben ser serializables. Si algún atributo no es serializable, debe marcarse como transitorio.

Si quieres saber si una clase estándar de Java es serializable, consulta la documentación de esa clase. Verificar si una instancia de una clase puede serializarse es muy sencillo: solo hay que comprobar si esa clase implementa la interfaz java.io.Serializable.


Serializar objeto

La clase ObjectOutputStream se utiliza para serializar un objeto. El siguiente ejemplo SerializeDemo crea una instancia de un objeto Employee y lo serializa en un archivo.

Después de ejecutar el programa, se crea un archivo llamado employee.ser. El programa no produce ninguna salida, pero puedes entender su funcionamiento examinando el código.

Nota:Al serializar un objeto en un archivo, según la convención estándar de Java, se le da al archivo la extensión .ser.

Código del archivo SerializeDemo.java:

import java.io.*; public class SerializeDemo { public static void main(String [] args) { Employee e = new Employee(); e.name = "Reyan Ali"; e.address = "Phokka Kuan, Ambehta Peer"; e.SSN = 11122333; e.number = 101; try { FileOutputStream fileOut = new FileOutputStream("/tmp/employee.ser"); ObjectOutputStream out = new ObjectOutputStream(fileOut); out.writeObject(e); out.close(); fileOut.close(); System.out.printf("Serialized data is saved in /tmp/employee.ser"); }catch(IOException i) { i.printStackTrace(); } } }

Deserializar objeto

El siguiente programa DeserializeDemo ejemplifica la deserialización; /tmp/employee.ser almacena el objeto Employee.

Código del archivo DeserializeDemo.java:

import java.io.*; public class DeserializeDemo { public static void main(String [] args) { Employee e = null; try { FileInputStream fileIn = new FileInputStream("/tmp/employee.ser"); ObjectInputStream in = new ObjectInputStream(fileIn); e = (Employee) in.readObject(); in.close(); fileIn.close(); }catch(IOException i) { i.printStackTrace(); return; }catch(ClassNotFoundException c) { System.out.println("Employee class not found"); c.printStackTrace(); return; } System.out.println("Deserialized Employee..."); System.out.println("Name: " + e.name); System.out.println("Address: " + e.address); System.out.println("SSN: " + e.SSN); System.out.println("Number: " + e.number); } }

El resultado de compilar y ejecutar el programa anterior es el siguiente:

Deserialized Employee...
Name: Reyan Ali
Address:Phokka Kuan, Ambehta Peer
SSN: 0
Number:101

Aquí hay que tener en cuenta los siguientes puntos:

El bloque try/catch en el método readObject() intenta capturar la excepción ClassNotFoundException. Para que la JVM pueda deserializar un objeto, debe ser capaz de encontrar la clase del código de bytes. Si la JVM no encuentra dicha clase durante el proceso de deserialización, lanza una excepción ClassNotFoundException.

Ten en cuenta que el valor de retorno del método readObject() se convierte en una referencia Employee.

Cuando el objeto se serializa, el valor del atributo SSN es 111222333, pero debido a que este atributo es transitorio, dicho valor no se envía al flujo de salida. Por lo tanto, después de la deserialización, el atributo SSN del objeto Employee es 0.

Otras extensiones