¿Qué es un serialVersionUID y por qué debería usarlo?
Eclipse emite advertencias cuando serialVersionUID
falta a.
La clase serializable Foo no declara un campo serialVersionUID final estático de tipo largo
¿Qué es serialVersionUID
y por qué es importante? Muestre un ejemplo en el que la falta serialVersionUID
causará un problema.
Los documentos java.io.Serializable
probablemente sean una explicación tan buena como la que obtendrá:
El tiempo de ejecución de serialización asocia con cada clase serializable un número de versión, llamado
serialVersionUID
, que se usa durante la deserialización para verificar que el remitente y el receptor de un objeto serializado hayan cargado clases para ese objeto que sean compatibles con respecto a la serialización. Si el receptor ha cargado una clase para el objeto que tiene unaserialVersionUID
clase diferente a la del remitente correspondiente, entonces la deserialización dará como resultado un archivoInvalidClassException
. Una clase serializable puede declarar la suya propiaserialVersionUID
explícitamente declarando un campo llamadoserialVersionUID
que debe ser estático, final y de tipolong
:
ANY-ACCESS-MODIFIER static final long serialVersionUID = 42L;
Si una clase serializable no declara explícitamente a
serialVersionUID
, entonces el tiempo de ejecución de serialización calculará unserialVersionUID
valor predeterminado para esa clase en función de varios aspectos de la clase, como se describe en la Especificación de serialización de objetos Java(TM). Sin embargo, se recomienda encarecidamente que todas las clases serializables declarenserialVersionUID
valores explícitamente, ya que elserialVersionUID
cálculo predeterminado es muy sensible a los detalles de la clase que pueden variar según las implementaciones del compilador y, por lo tanto, pueden generar resultados inesperadosInvalidClassExceptions
durante la deserialización. Por lo tanto, para garantizar unserialVersionUID
valor consistente en diferentes implementaciones del compilador Java, una clase serializable debe declarar unserialVersionUID
valor explícito. También se recomienda encarecidamente que lasserialVersionUID
declaraciones explícitas utilicen el modificador privado siempre que sea posible, ya que dichas declaraciones se aplican sólo a la clase que se declara inmediatamente; losserialVersionUID
campos no son útiles como miembros heredados.
Si está serializando solo porque tiene que serializar por el bien de la implementación (a quién le importa si serializa para un HTTPSession
, por ejemplo... si está almacenado o no, probablemente no le importe de-serializing
un objeto de formulario), entonces puede ignora esto.
Si realmente estás usando la serialización, solo importa si planeas almacenar y recuperar objetos usando la serialización directamente. Representa la serialVersionUID
versión de su clase y debe incrementarla si la versión actual de su clase no es compatible con su versión anterior.
La mayoría de las veces, probablemente no utilizará la serialización directamente. Si este es el caso, genere un valor predeterminado SerialVersionUID
haciendo clic en la opción de solución rápida y no se preocupe.
No puedo dejar pasar esta oportunidad de promocionar el libro Effective Java (segunda edición) de Josh Bloch. El Capítulo 10 es un recurso indispensable sobre la serialización de Java.
Según Josh, el UID generado automáticamente se genera en función del nombre de una clase, las interfaces implementadas y todos los miembros públicos y protegidos. Cambiar cualquiera de estos de cualquier manera cambiará el archivo serialVersionUID
. Por lo tanto, no necesita meterse con ellos solo si está seguro de que nunca se serializará más de una versión de la clase (ya sea entre procesos o se recuperará del almacenamiento en un momento posterior).
Si los ignora por ahora y luego descubre que necesita cambiar la clase de alguna manera pero mantener la compatibilidad con la versión anterior de la clase, puede usar la herramienta JDK serialver para generar la clase anteriorserialVersionUID
y configurarla explícitamente. en la nueva clase. (Dependiendo de sus cambios, es posible que también necesite implementar una serialización personalizada agregando métodos y ; consulte javadoc o el capítulo 10 mencionado anteriormente).writeObject
readObject
Serializable
Puede decirle a Eclipse que ignore estas advertencias de serialVersionUID:
Ventana > Preferencias > Java > Compilador > Errores/Advertencias > Posibles problemas de programación
En caso de que no lo sepas, hay muchas otras advertencias que puedes habilitar en esta sección (o incluso informar algunas como errores), muchas de las cuales son muy útiles:
- Posibles problemas de programación: posible asignación booleana accidental
- Posibles problemas de programación: acceso al puntero nulo
- Código innecesario: la variable local nunca se lee
- Código innecesario: verificación nula redundante
- Código innecesario: conversión innecesaria o 'instancia de'
y muchos más.
serialVersionUID
facilita el control de versiones de datos serializados. Su valor se almacena con los datos al serializar. Al deserializar, se verifica la misma versión para ver cómo los datos serializados coinciden con el código actual.
Si desea versionar sus datos, normalmente comienza con serialVersionUID
0 y lo aumenta con cada cambio estructural en su clase que altera los datos serializados (agregando o eliminando campos no transitorios).
El mecanismo de deserialización incorporado ( in.defaultReadObject()
) se negará a deserializar versiones antiguas de los datos. Pero si lo desea, puede definir su propia función readObject() que puede leer datos antiguos. Este código personalizado puede luego verificar serialVersionUID
para saber en qué versión se encuentran los datos y decidir cómo deserializarlos. Esta técnica de control de versiones es útil si almacena datos serializados que sobreviven a varias versiones de su código.
Pero almacenar datos serializados durante un período de tiempo tan largo no es muy común. Es mucho más común usar el mecanismo de serialización para escribir datos temporalmente, por ejemplo, en un caché o enviarlos a través de la red a otro programa con la misma versión de las partes relevantes del código base.
En este caso no le interesa mantener la compatibilidad con versiones anteriores. Sólo le preocupa asegurarse de que las bases de código que se comunican tengan realmente las mismas versiones de las clases relevantes. Para facilitar dicha verificación, debe mantener el serialVersionUID
mismo estado anterior y no olvidar actualizarlo al realizar cambios en sus clases.
Si olvida actualizar el campo, podría terminar con dos versiones diferentes de una clase con estructura diferente pero con el mismo archivo serialVersionUID
. Si esto sucede, el mecanismo predeterminado ( in.defaultReadObject()
) no detectará ninguna diferencia e intentará deserializar los datos incompatibles. Ahora podría terminar con un error críptico de tiempo de ejecución o una falla silenciosa (campos nulos). Este tipo de errores pueden ser difíciles de encontrar.
Entonces, para ayudar en este caso de uso, la plataforma Java le ofrece la opción de no configurarlo serialVersionUID
manualmente. En su lugar, se generará un hash de la estructura de clases en tiempo de compilación y se utilizará como identificación. Este mecanismo garantizará que nunca tenga estructuras de clases diferentes con la misma identificación, por lo que no obtendrá estos errores de serialización en tiempo de ejecución difíciles de rastrear mencionados anteriormente.
Pero la estrategia de identificación generada automáticamente tiene un inconveniente. Es decir, que los identificadores generados para la misma clase pueden diferir entre compiladores (como lo mencionó Jon Skeet anteriormente). Entonces, si comunica datos serializados entre código compilado con diferentes compiladores, se recomienda mantener los identificadores manualmente de todos modos.
Y si es compatible con versiones anteriores de sus datos, como en el primer caso de uso mencionado, probablemente también desee mantener la identificación usted mismo. Esto con el fin de obtener identificadores legibles y tener un mayor control sobre cuándo y cómo cambian.