¿Qué es un serialVersionUID y por qué debería usarlo?

Resuelto ashokgelal asked hace 16 años • 26 respuestas

Eclipse emite advertencias cuando serialVersionUIDfalta a.

La clase serializable Foo no declara un campo serialVersionUID final estático de tipo largo

¿Qué es serialVersionUIDy por qué es importante? Muestre un ejemplo en el que la falta serialVersionUIDcausará un problema.

ashokgelal avatar Nov 13 '08 06:11 ashokgelal
Aceptado

Los documentos java.io.Serializableprobablemente 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 una serialVersionUIDclase diferente a la del remitente correspondiente, entonces la deserialización dará como resultado un archivo InvalidClassException. Una clase serializable puede declarar la suya propia serialVersionUIDexplícitamente declarando un campo llamado serialVersionUIDque debe ser estático, final y de tipo long:

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á un serialVersionUIDvalor 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 declaren serialVersionUIDvalores explícitamente, ya que el serialVersionUIDcá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 inesperados InvalidClassExceptionsdurante la deserialización. Por lo tanto, para garantizar un serialVersionUIDvalor consistente en diferentes implementaciones del compilador Java, una clase serializable debe declarar un serialVersionUIDvalor explícito. También se recomienda encarecidamente que las serialVersionUIDdeclaraciones 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; los serialVersionUIDcampos no son útiles como miembros heredados.

Jon Skeet avatar Nov 12 '2008 23:11 Jon Skeet

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-serializingun 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 serialVersionUIDversió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 SerialVersionUIDhaciendo clic en la opción de solución rápida y no se preocupe.

MetroidFan2002 avatar Nov 13 '2008 04:11 MetroidFan2002

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).writeObjectreadObjectSerializable

Scott Bale avatar Nov 12 '2008 23:11 Scott Bale

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.

matt b avatar Nov 13 '2008 01:11 matt b

serialVersionUIDfacilita 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 serialVersionUID0 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 serialVersionUIDpara 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 serialVersionUIDmismo 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 serialVersionUIDmanualmente. 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.

Alexander Torstling avatar Oct 03 '2012 06:10 Alexander Torstling