Skip to content

🚀 Serialización de Objetos en Java

La serialización en Java permite convertir objetos en una secuencia de bytes para que puedan ser almacenados en archivos, enviados por red o guardados en bases de datos. Luego, esos bytes pueden ser desserializados para reconstruir el objeto original.


¿Por qué es Importante la Serialización?

📌 Permite guardar objetos en archivos o bases de datos para su posterior uso.
📌 Facilita la comunicación en red (envío de objetos entre sistemas).
📌 Es clave en tecnologías como RMI (Remote Method Invocation), donde se envían objetos entre JVMs.
📌 Ayuda en la caché y persistencia de datos en aplicaciones grandes.


Cómo Serializar y Deserializar en Java

Para que un objeto sea serializable, su clase debe implementar la interfaz Serializable.

📌 Ejemplo Básico de Serialización

import java.io.*;

// Implementamos Serializable
class Persona implements Serializable {
    private static final long serialVersionUID = 1L; // ID de versión para compatibilidad
    private String nombre;
    private int edad;

    public Persona(String nombre, int edad) {
        this.nombre = nombre;
        this.edad = edad;
    }

    @Override
    public String toString() {
        return "Persona{nombre='" + nombre + "', edad=" + edad + "}";
    }
}

public class SerializacionEjemplo {
    public static void main(String[] args) {
        Persona persona = new Persona("Kevin", 25);

        // Serializar objeto
        try (ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("persona.ser"))) {
            oos.writeObject(persona);
            System.out.println("Objeto serializado con éxito.");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

¿Qué hicimos aquí?
1️⃣ Creamos la clase Persona e implementamos Serializable.
2️⃣ Guardamos el objeto en un archivo (persona.ser).


📌 Ejemplo de Deserialización

Ahora, recuperamos el objeto serializado.

import java.io.*;

public class DeserializacionEjemplo {
    public static void main(String[] args) {
        // Deserializar objeto
        try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream("persona.ser"))) {
            Persona persona = (Persona) ois.readObject();
            System.out.println("Objeto deserializado: " + persona);
        } catch (IOException | ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
}

¿Qué sucede aquí?
1️⃣ Leemos los bytes desde el archivo persona.ser.
2️⃣ Los reconstruimos como un objeto Persona.
3️⃣ Imprimimos el objeto en la consola.


Conceptos Claves en Serialización

📌 1️⃣ serialVersionUID

Es un identificador único para una clase serializable.

private static final long serialVersionUID = 1L;

🔹 Si cambias la estructura de la clase y no actualizas serialVersionUID, la deserialización fallará.

📌 2️⃣ Campos transient (Exclusión de Serialización)

Si hay datos que no quieres serializar, usa transient.

class Persona implements Serializable {
    private static final long serialVersionUID = 1L;
    private String nombre;
    private transient int edad; // No se serializará
}

🔹 Al deserializar, edad tomará su valor por defecto (0 para int).


Serialización Personalizada con Externalizable

Si queremos mayor control sobre el proceso de serialización/deserialización, usamos Externalizable.

📌 Ejemplo de Externalizable

import java.io.*;

class Persona implements Externalizable {
    private String nombre;
    private int edad;

    public Persona() { } // Necesario para Externalizable

    public Persona(String nombre, int edad) {
        this.nombre = nombre;
        this.edad = edad;
    }

    @Override
    public void writeExternal(ObjectOutput out) throws IOException {
        out.writeUTF(nombre);
        out.writeInt(edad);
    }

    @Override
    public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
        nombre = in.readUTF();
        edad = in.readInt();
    }

    @Override
    public String toString() {
        return "Persona{nombre='" + nombre + "', edad=" + edad + "}";
    }
}

Ventajas de Externalizable
✔️ Mayor control sobre qué datos se serializan y cómo.
✔️ Puede comprimir datos antes de guardarlos.


Serialización en JSON con Jackson o Gson

Para aplicaciones modernas, es común usar JSON en lugar de Serializable.

📌 Ejemplo con Gson

import com.google.gson.Gson;

class Persona {
    private String nombre;
    private int edad;

    public Persona(String nombre, int edad) {
        this.nombre = nombre;
        this.edad = edad;
    }
}

public class GsonEjemplo {
    public static void main(String[] args) {
        Gson gson = new Gson();
        Persona persona = new Persona("Kevin", 25);

        // Convertir a JSON
        String json = gson.toJson(persona);
        System.out.println("JSON: " + json);

        // Convertir de JSON a Objeto
        Persona nuevaPersona = gson.fromJson(json, Persona.class);
        System.out.println("Objeto deserializado: " + nuevaPersona);
    }
}

Ventajas de JSON
✔️ Más portable y legible que Serializable.
✔️ Compatible con APIs REST y bases de datos NoSQL.


🎯 Conclusión

📌 Usa Serializable cuando necesites guardar o transmitir objetos en un sistema Java puro.
📌 Usa Externalizable si necesitas control total sobre la serialización.
📌 Usa JSON (Gson, Jackson) si interactúas con APIs REST o bases de datos NoSQL.

Serialización en redes o bases de datos

🚀 Serialización en Redes y Bases de Datos en Java

Ahora que ya comprendemos la serialización de objetos en Java, vamos a ver cómo aplicarla en redes y bases de datos. Esto es clave para la comunicación entre sistemas y el almacenamiento eficiente de objetos.


1. Serialización en Redes (Sockets)

La serialización permite enviar objetos entre clientes y servidores a través de sockets. Esto es útil para aplicaciones de mensajería, juegos en red, APIs distribuidas, etc.

🔥 Ejemplo: Cliente-Servidor con Objetos Serializados

Vamos a construir una aplicación donde un cliente envía un objeto al servidor, y este lo recibe y lo imprime.

📌 1️⃣ Definir la Clase Serializable

import java.io.Serializable;

class Persona implements Serializable {
    private static final long serialVersionUID = 1L;
    private String nombre;
    private int edad;

    public Persona(String nombre, int edad) {
        this.nombre = nombre;
        this.edad = edad;
    }

    @Override
    public String toString() {
        return "Persona{nombre='" + nombre + "', edad=" + edad + "}";
    }
}

📌 2️⃣ Servidor que Recibe el Objeto

El servidor escucha conexiones y deserializa el objeto recibido.

import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;

public class Servidor {
    public static void main(String[] args) {
        try (ServerSocket serverSocket = new ServerSocket(5000)) {
            System.out.println("Servidor esperando conexiones...");
            Socket socket = serverSocket.accept();
            System.out.println("Cliente conectado.");

            ObjectInputStream ois = new ObjectInputStream(socket.getInputStream());
            Persona persona = (Persona) ois.readObject();
            System.out.println("Objeto recibido: " + persona);

            ois.close();
            socket.close();
        } catch (IOException | ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
}

📌 3️⃣ Cliente que Envía el Objeto

El cliente crea un objeto Persona y lo envía al servidor.

import java.io.*;
import java.net.Socket;

public class Cliente {
    public static void main(String[] args) {
        try (Socket socket = new Socket("localhost", 5000);
             ObjectOutputStream oos = new ObjectOutputStream(socket.getOutputStream())) {

            Persona persona = new Persona("Kevin", 25);
            oos.writeObject(persona);
            System.out.println("Objeto enviado al servidor.");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

Explicación
1️⃣ El servidor espera una conexión y lee el objeto serializado.
2️⃣ El cliente crea un objeto Persona y lo envía al servidor.
3️⃣ El servidor deserializa y muestra la información.

🔹 Este método se usa en sistemas distribuidos y microservicios en Java.


2. Serialización en Bases de Datos

En ocasiones, en lugar de almacenar los datos de un objeto en múltiples columnas, podemos serializarlo y guardarlo en una columna tipo BLOB (Binary Large Object).

🔥 Ejemplo: Guardar un Objeto en MySQL

📌 1️⃣ Crear la Base de Datos

CREATE TABLE personas (
    id INT AUTO_INCREMENT PRIMARY KEY,
    datos LONGBLOB
);

📌 2️⃣ Serializar y Guardar en MySQL

import java.io.*;
import java.sql.*;

public class SerializacionBD {
    public static void main(String[] args) {
        Persona persona = new Persona("Kevin", 25);

        try (Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/test", "root", "password");
             PreparedStatement ps = conn.prepareStatement("INSERT INTO personas (datos) VALUES (?)")) {

            // Serializar objeto
            ByteArrayOutputStream bos = new ByteArrayOutputStream();
            ObjectOutputStream oos = new ObjectOutputStream(bos);
            oos.writeObject(persona);
            oos.close();

            byte[] personaBytes = bos.toByteArray();
            ps.setBytes(1, personaBytes);
            ps.executeUpdate();

            System.out.println("Objeto almacenado en la base de datos.");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

¿Qué hace este código?
1️⃣ Convierte el objeto en bytes con ObjectOutputStream.
2️⃣ Guarda los bytes en la base de datos en una columna BLOB.


📌 3️⃣ Leer y Deserializar desde MySQL

import java.io.*;
import java.sql.*;

public class DeserializacionBD {
    public static void main(String[] args) {
        try (Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/test", "root", "password");
             Statement stmt = conn.createStatement();
             ResultSet rs = stmt.executeQuery("SELECT datos FROM personas WHERE id=1")) {

            if (rs.next()) {
                byte[] personaBytes = rs.getBytes("datos");

                ByteArrayInputStream bis = new ByteArrayInputStream(personaBytes);
                ObjectInputStream ois = new ObjectInputStream(bis);
                Persona persona = (Persona) ois.readObject();
                ois.close();

                System.out.println("Objeto recuperado de la base de datos: " + persona);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

¿Qué hacemos aquí?
1️⃣ Leemos los bytes de la BD.
2️⃣ Los deserializamos para obtener el objeto original.


🔥 Comparación: Serialización con BLOB vs JSON

Método Ventajas Desventajas
BLOB (Serializable) ✅ Guarda el objeto completo. ✅ Ideal para objetos complejos. ❌ No es legible por humanos. ❌ Solo se puede leer en Java.
JSON (Gson/Jackson) ✅ Fácil de leer. ✅ Compatible con otras tecnologías. ❌ No almacena comportamiento del objeto.

[!IMPORTANT] > 📌 Si necesitas interoperabilidad con otros lenguajes (Python, JavaScript, etc.), usa JSON.


🎯 Conclusión

🔹 Serialización en redes permite enviar objetos entre cliente-servidor usando sockets.
🔹 Serialización en bases de datos permite almacenar objetos en BLOB o convertirlos a JSON.
🔹 Para APIs modernas, usar JSON es más eficiente y portable.