JavaRush /Blog Java /Random-ES /Cómo funciona la serialización en Java
ramhead
Nivel 13

Cómo funciona la serialización en Java

Publicado en el grupo Random-ES
En este artículo explicaremos qué es la serialización y cómo funciona en Java. Cómo funciona la serialización en Java - 1

Introducción

La serialización de objetos es la capacidad de un objeto de almacenar una copia completa de sí mismo y de cualquier otro objeto al que haga referencia mediante un flujo de salida (por ejemplo, en un archivo externo). De esta manera, el objeto se puede recrear a partir de la copia serializada (guardada) un poco más tarde, cuando sea necesario. La serialización de objetos, una nueva característica introducida en JDK 1.1, proporciona una función para convertir grupos u objetos individuales, en un flujo de bits o una matriz de bytes, para su almacenamiento o transmisión a través de una red. Y como se indicó, un flujo de bits o una matriz de bytes determinados se pueden volver a convertir en objetos Java. Esto sucede principalmente de forma automática gracias a las clases ObjectInputStreamy ObjectOutputStream. El programador puede decidir implementar esta funcionalidad implementando la interfaz Serializableal crear la clase. El proceso de serialización también se conoce como clasificación de objetos , mientras que la deserialización se conoce como desclasificación . La serialización es un mecanismo que permite que un objeto guarde una copia de sí mismo y de todos los demás objetos a los que hace referencia ese objeto en un archivo externo mediante la extensión ObjectOutputStream. Los objetos guardados pueden ser estructuras de datos, diagramas, objetos de clase JFrameo cualquier otro objeto, independientemente de su tipo. Al mismo tiempo, la serialización almacena información sobre de qué tipo es un objeto para que luego, cuando se deserialice, esa información se utilice para recrear el tipo exacto de objeto que era. Entonces, la serialización proporciona las siguientes capacidades:
  • Un sistema para almacenar objetos, es decir: guardar sus propiedades en un archivo externo, en un disco o en una base de datos.
  • Sistema de llamada a trámite remoto.
  • Un sistema de distribución de objetos, por ejemplo, en componentes de software como COM, COBRA.
  • Sistema de identificación de cambios en datos variables a lo largo del tiempo.
Para comprender completamente el concepto de serialización, es necesario tener una comprensión clara de los otros dos conceptos: persistencia de objetos y persistencia de subprocesos. Aquí hablaremos un poco de cada uno de ellos para poder recordar. Una explicación completa de ellos requeriría un capítulo separado para cada uno de estos conceptos.

Corrientes:

Cada programa debe escribir sus datos en una ubicación de almacenamiento o tubería, y cada programa debe leer datos de una tubería o ubicación de almacenamiento. En Java, estos canales donde los programas escriben y desde los cuales los programas leen datos se denominan Streams ( Stream) . Cómo funciona la serialización en Java - 2
Figura 1. Representación gráfica de Threads
Las corrientes se dividen principalmente en dos tipos:
  • Clases de flujo de bytes llamadas *Streams
  • Clases de flujo de caracteres llamadas *Reader y *Writer
Cada flujo de escritura de datos contiene un conjunto de métodos de escritura. Y cada hilo de lectura de datos, en consecuencia, tiene un conjunto similar de métodos de lectura. Una vez creado el hilo, se deben llamar a todos estos métodos.

Persistencia

La persistencia de un objeto es la capacidad de un objeto de vivir o, en otras palabras, de "sobrevivir" a la ejecución de un programa. Esto significa que cualquier objeto creado en tiempo de ejecución es destruido por el eliminador de JVM cada vez que ese objeto ya no se utiliza. Pero si se implementa la API de persistencia, estos objetos no serán destruidos por el limpiador JVM, sino que se les permitirá "vivir", lo que también hace posible acceder a ellos la próxima vez que se inicie la aplicación. En otras palabras, la persistencia significa que hay una vida útil para un objeto, independiente de la vida útil de la aplicación que se está ejecutando. Una forma de implementar la persistencia es almacenar objetos en algún lugar de un archivo o base de datos externo y luego restaurarlos más adelante utilizando esos archivos o la base de datos como fuentes. Aquí es donde entra en juego la serialización. Cualquier objeto no persistente existe mientras la JVM se esté ejecutando. Los objetos serializados son simplemente objetos convertidos en secuencias, que luego se guardan en un archivo externo o se transfieren a través de una red para su almacenamiento y recuperación.

Implementación de la interfaz serializable.

Cualquier clase debe implementar una interfaz java.io.Serializablepara serializar objetos de esa clase. La interfaz Serializableno tiene métodos y solo marca la clase para que pueda identificarse como serializable. Sólo se pueden guardar los campos de un objeto de clase serializado. Los métodos o constructores no se almacenan como parte del flujo serializado. Si algún objeto actúa como referencia a otro objeto, entonces los campos de ese objeto también se serializan si la clase de ese objeto implementa la interfaz Serializable. En otras palabras, el gráfico de este objeto así obtenido es completamente serializable. Un gráfico de objetos incluye un árbol o estructura de campos de un objeto y sus subobjetos. Dos clases principales que ayudan a implementar la interfaz Seriliazable:
  • ObjectInputStream
  • ObjectOutputStream
Listado 1. Ejemplo de una clase simple para mostrar la serialización
import java.io.*;
public class RandomClass implements Serializable {
 // Генерация рандомного значения
 private static int r() {
        return (int)(Math.random() * 10);
 }
    private int data[];
    // Конструктор
public RandomClass() {
        datafile = new int[r()];
        for (int i=0; i<datafile.length; i++)
        datafile[i]=r();
 }
    public void printout() {
 System.out.println("This RandomClass has "+datafile.length+" random integers");
 for (int i=0; i<datafile.length; i++) {
        System.out.print(datafile[i]+":");
        System.out.println();
    }
}
En el código anterior, se crea una clase que es serializable porque "marcado" por la interfaz de serialización. La clase crea una matriz de números enteros aleatorios cuando se crea una instancia de la misma. El siguiente código muestra la capacidad de escribir objetos en una secuencia utilizando la extensión ObjectOutputStream. El programa tiene una serie de números enteros, pero para la serialización no tenemos que iterar sobre sus objetos internos. La interfaz Seriliazablese encarga de esto automáticamente. Listado 2. Un ejemplo simple de serialización de objetos para enviarlos a un archivo
import java.io.*;
import java.util.*;
public class OutSerialize {
    public static void main (String args[]) throws IOException {
        RandomClass rc1 = new RandomClass();
        RandomClass rc2 = new RandomClass();
//создание цепи потоков с потоком вывода un objetoа в конце
ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("objects.dat"));
        Date now = new Date(System.currentTimeMillis());
//java.util.* был импортирован для использования класса Date
        out.writeObject(now);
        out.writeObject(rc1);
        out.writeObject(rc2);
out.close();
        System.out.println("I have written:");
System.out.println("A Date object: "+now);
        System.out.println("Two Group of randoms");
rc1.printout();
rc2.printout();
 }
}
El siguiente código demuestra las capacidades de la clase ObjectInputStream, que lee datos serializados de un archivo externo en un programa. Tenga en cuenta que los objetos se leen en el mismo orden en que se escribieron en el archivo. Listado 3. Lectura de objetos serializados o Deserialización
import java.io.*;
import java.util.*;
public class InSerialize {
 public static void main (String args[]) throws  IOException, ClassNotFoundException {
    ObjectInputStream in =  new ObjectInputStream (new FileInputStream("objects.dat"));
 Date d1 = (Date)in.readObject();
 RandomClass rc1 = (RandomClass)in.readObject();
    RandomClass rc2 = (RandomClass)in.readObject();
    System.out.println("I have read:");
    System.out.println("A Date object: "+d1);
    System.out.println("Two Group of randoms");
    rc1.printout();
rc2.printout();
 }
}
Casi todas las clases de Java se pueden serializar, incluidas las clases AWT. Un marco, que es una ventana, contiene un conjunto de componentes gráficos. Si el marco está serializado, el motor de serialización se encarga de ello y serializa todos sus componentes y datos (posición, contenido, etc.). Algunos objetos de clase Java no se pueden serializar porque contienen datos que hacen referencia a recursos efímeros del sistema operativo. Por ejemplo clases java.io.FileInputStreamy java.lang.Thread. Si un objeto contiene referencias a elementos no serializables, toda la operación de serialización fallará y se generará una excepción NotSerializableException. Si algún objeto hace referencia a una referencia de un objeto no serializado, entonces se puede serializar usando la palabra clave transitoria . Listado 4. Creando objetos serializables usando la palabra clave transitoria
public class Sclass implements Serializable{
public transient Thread newThread;
//помните, что поток(поток параллельного исполнения) по умолчанию не сериализуемый класс
    private String studentID;
    private int sum;
}

Seguridad en la serialización

Serializar una clase en Java implica pasar todos sus datos a un archivo o base de datos externo a través de una secuencia. Podemos limitar los datos que se serializarán cuando queramos. Hay dos maneras de hacer esto:
  • Cada parámetro de clase declarado como transitorio no está serializado (de forma predeterminada, todos los parámetros de clase están serializados)
  • O bien, cada parámetro de la clase que queremos serializar está marcado con una etiqueta Externalizable(de forma predeterminada, no se serializa ningún parámetro).
Un campo de datos no se serializará con ObjectOutputStream, cuando se llame a un objeto, si el campo de datos de ese objeto está marcado como transitorio . Por ejemplo: private transient String password. Por otro lado, para declarar explícitamente los datos de un objeto como serializables, debemos marcar la clase como que escribe y lee ExternalizablewriteExternalexplícitamente los datos de ese objeto.readExteranl

Conclusión

La función de serialización de objetos se utiliza en muchos sistemas distribuidos como una forma de transferir datos. Pero la serialización revela detalles ocultos, destruyendo así la autenticidad de los tipos de datos abstractos, lo que a su vez destruye la encapsulación. Al mismo tiempo, es bueno saber que los datos del objeto serializado son los mismos datos que estaban en el objeto original. Esta también es una gran oportunidad para implementar una interfaz ObjectInputValidationy anular un método validateObject(), incluso si se utilizan varias líneas de código. Si no se encuentra el objeto, podemos lanzar una excepción apropiada InvalidObjectException. Artículo original: Cómo funciona la serialización en Java
Comentarios
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION