SerialVersionUID en Java

Sheeraz Gul 12 octubre 2023
SerialVersionUID en Java

Este tutorial demuestra cómo usar SerialVersionUID en Java.

SerialVersionUID en Java

El SerialVersionUID se utiliza en la serialización. La serialización es un proceso en el que convertimos un objeto en un flujo de bytes para almacenar los datos y enviarlos a alguna parte, y la deserialización es el proceso inverso.

Durante el proceso de serialización, el tiempo de ejecución de Java asociará un número de versión con cada clase Serializable; ese número se llama SerialVersionUID.

El SerialVersionUID se usa para verificar que el remitente y el receptor de los datos serializados han cargado las clases para esos datos y son compatibles en términos de serialización.

Por ejemplo, si un receptor ha cargado una clase para el objeto con un SerialVersionUID diferente al de la clase del remitente correspondiente, arrojará la InvalidClassException.

Podemos declarar nuestro propio SerialVersionUID para la clase Serializable. El SerialVersionUID se declarará como Static Final y de tipo Long.

Vea la sintaxis:

private static final long serialVersionUID = 10L;

Probemos un ejemplo que implementa serialización y deserialización con el SerialVersionUID. Ver ejemplo:

package delftstack;

import java.io.*;
import java.util.logging.Logger;

public class Example implements java.io.Serializable {
  // The Default serial version uid
  private static final long serialVersionUID = 4L;
  // random name
  private static final String File_Name = "ExampleClassBytes.ser";
  private static final Logger logger_File = Logger.getLogger("");
  // Few data fields Which will be able to serialize
  private static String Static_Variable;
  private int Integer_Variable;

  // Few data fields Which will not be able to serialize
  transient private String Transient_Variable = "this is a transient instance field";
  private Thread Thread_Class;

  private static Object readIn() throws IOException, ClassNotFoundException {
    ObjectInputStream Object_Input_Stream =
        new ObjectInputStream(new FileInputStream(new File(File_Name)));
    return Object_Input_Stream.readObject();
  }

  private static void writeOut(java.io.Serializable object) throws IOException {
    ObjectOutputStream Object_Output_Stream =
        new ObjectOutputStream(new FileOutputStream(new File(File_Name)));
    Object_Output_Stream.writeObject(object);
    Object_Output_Stream.close();
  }

  @Override
  public String toString() {
    return "Example Class:- final static fileName is: " + File_Name + ", final static logger is: "
        + logger_File + ", the non-final static staticVariable is: " + Static_Variable
        + ", the instance intVariable is: " + Integer_Variable
        + ", the transient instance Variable is: " + Transient_Variable
        + ", the non-serializable instance field threadClass is : " + Thread_Class;
  }

  public static void main(String[] args) throws IOException, ClassNotFoundException {
    // Serialization

    Example Demo = new Example();
    Demo.Integer_Variable = 1;
    Static_Variable = "this is the static variable";
    writeOut(Demo);
    System.out.println("Example Class to be saved: " + Demo);

    // De-serialization

    System.out.println("Example Class deserialized: " + readIn());
  }
}

Si la clase Serializable no declara explícitamente un SerialVersionUID, el tiempo de ejecución calculará el SerialVersionUID predeterminado para esa clase en función de los aspectos. Ahora veamos el resultado del código anterior.

Example Class to be saved: Example Class:- final static fileName is: ExampleClassBytes.ser, final static logger is: java.util.logging.LogManager$RootLogger@27973e9b, the non-final static staticVariable is: this is the static variable, the instance intVariable is: 1, the transient instance Variable is: this is a transient instance field, the non-serializable instance field threadClass is : null
Example Class deserialized: Example Class:- final static fileName is: ExampleClassBytes.ser, final static logger is: java.util.logging.LogManager$RootLogger@27973e9b, the non-final static staticVariable is: this is the static variable, the instance intVariable is: 1, the transient instance Variable is: null, the non-serializable instance field threadClass is : null

Algunos puntos importantes sobre el SerialVersionUID basados en el escenario anterior:

  1. Los campos estáticos y transitorios se ignoran durante la serialización y, después de la deserialización, los campos finales transitorios y no estáticos se anularán.
  2. Para la serialización, necesitamos manejar la IOException, y para la deserialización, necesitamos IOException y ClassNotFoundException. Eso significa que el tipo de clase deserializado debe estar en la ruta de clases.
  3. Los métodos ObjectInputStream.readObject() y ObjectOutputStream.writeObject(object) se utilizan para la operación de serialización y deserialización.
  4. La serialización y la deserialización se pueden utilizar para clonar y copiar los objetos, lo que es comparativamente más lento que las operaciones de clonación regulares.
  5. Se toleran las instancias no inicializadas, no serializables y no transitorias.
  6. Al modificar la clase que implementa el java.io.Serializable, debemos tener cuidado porque si una clase no contiene un SerialVersionUID, el compilador generará un SerialVersionUID.
  7. Calcular el SerialVersionUID se basa no solo en los campos, sino también en otros aspectos como constructores, cláusulas de implementación, etc. Esto significa que debemos declarar explícitamente un SerialVersionUID, que también mantendrá la compatibilidad con versiones anteriores.
Sheeraz Gul avatar Sheeraz Gul avatar

Sheeraz is a Doctorate fellow in Computer Science at Northwestern Polytechnical University, Xian, China. He has 7 years of Software Development experience in AI, Web, Database, and Desktop technologies. He writes tutorials in Java, PHP, Python, GoLang, R, etc., to help beginners learn the field of Computer Science.

LinkedIn Facebook