Historia del tema
Desde el inicio de Java, surgió la necesidad de guardar objetos entre sesiones de trabajo de aplicaciones: transmitir por red, guardar en bases de datos o en disco. Para esto se creó la interfaz Serializable, que permite convertir objetos en un flujo de bytes y viceversa (serialización y deserialización).
Problema
Si una clase no implementa la interfaz Serializable, intentar serializar su instancia lanzará una excepción. Además, la serialización guarda no solo los valores de los campos, sino también su estado, por lo que una implementación incorrecta puede llevar a vulnerabilidades inesperadas, errores al recuperar el objeto o incluso pérdida de datos.
Solución
La interfaz Serializable es una interfaz de marcador, es decir, no contiene métodos. Para una correcta serialización, se debe especificar explícitamente serialVersionUID, así como usar la palabra clave transient para los campos que no deben ser serializados.
Ejemplo de código:
import java.io.Serializable; public class User implements Serializable { private static final long serialVersionUID = 1L; private String username; private transient String password; // no será serializado public User(String username, String password) { this.username = username; this.password = password; } }
Características clave:
¿Es obligatorio declarar explícitamente el campo serialVersionUID?
No, no es obligatorio, pero si no se declara, se generará automáticamente. Sin embargo, si se realizan cambios en la clase, la recuperación de la versión serializada antigua puede llevar a un InvalidClassException. Por lo tanto, es mejor siempre declarar explícitamente este campo.
¿Se serializan los campos estáticos?
No, solo se serializan los campos no estáticos (instance). Los campos estáticos pertenecen a la clase y no al objeto, por lo que sus valores no se guardan ni se recuperan durante la serialización y deserialización.
¿Se puede serializar un objeto cuyas propiedades no implementan Serializable?
No, si al menos un campo no estático no es serializable y no se declara como transient, intentar serializarlo generará una excepción NotSerializableException.
En una aplicación de almacenamiento en caché de usuarios no se especificó serialVersionUID, y al hacer cambios en el código se modificó la estructura de la clase User. Al iniciar la aplicación, se produjo un InvalidClassException y se perdieron todos los datos serializados.
Ventajas:
Desventajas:
En un proyecto similar, siempre se especificó explícitamente serialVersionUID y todos los campos que no debían ser serializados se marcaron como transient. Gracias a esto, los objetos serializados se cargaron con éxito después de un cambio menor en la estructura de la clase.
Ventajas:
Desventajas: