2010-07-19 20 views
39

Sé que puedo usar serialVersionUID para controlar la versión de las clases. Y leí que puedo agregar o eliminar campos y la clase seguirá siendo compatible, solo usará los valores predeterminados.¿Cuándo debo cambiar el serialVersionUID?

Cuando debe ¿Cambio el serialVersionUID?

+0

Relacionados con https://stackoverflow.com/questions/3678136/managing-several-versions-of-serialized-java-objects/14946099#14946099 – Gray

Respuesta

44

El valor del campo serialVersionUID idealmente debería cambiarse cuando se realizan cambios incompatibles en la estructura de la clase. La lista completa de cambios incompatibles se enumera en el Java Object Serialization Specification.

Para ampliar aún más, los cambios incompatibles en una clase evitarán que el mecanismo de deserialización cree una instancia del objeto, porque hay información en la secuencia que no se correlaciona con la definición de clase actual.

+0

Gracias, buena respuesta – Kyle

+1

No, no lo es. Los cambios incompatibles enumerados en la Especificación son los que darán lugar a excepciones cuando se intente. Los que simplemente no se asignan a la definición de clase actual son * cambios * compatibles, y hay una larga lista de ellos también. – EJP

+0

* Para ampliar aún más, los cambios [...] incompatibles evitan que el mecanismo de deserialización cree una instancia *: ¿Esta respuesta no equivale a decir que debería cambiar 'serialVersionUID' para hacer que el mecanismo de deserialización arroje una excepción, aunque pueda Ya lo hago sin mi ayuda, ya que es un cambio incompatible que impide que dicho mecanismo funcione? Si ese es el caso, creo que debería haber una aclaración sobre cómo es útil. (Estoy dudando aquí porque [la respuesta de EJP] (https://stackoverflow.com/a/3288280/1036728) tiene mucho más sentido.) – antak

3

Si no se especifica un campo serialVersionUID en sus clases Serializable, el compilador de Java especificará uno para usted - en esencia se trata de un hash del nombre de la clase, los nombres de interfaces, métodos y campos de la clase. Sin embargo, los métodos se pueden modificar en cualquier momento, por lo que si necesita cambiar la forma en que se deserializa una clase almacenada, puede anular el método readObject. Sin embargo, si especifica el campo serialVersionUID en su código, el compilador no anulará eso incluso si realiza cambios incompatibles, lo que puede dar como resultado una excepción en tiempo de ejecución: su IDE o compilador no le dará una advertencia. . (EDITAR - gracias EJP) Los IDEs como Eclipse pueden insertar el UID del compilador por usted, si desea comprobar fácilmente cómo ve el compilador ciertos cambios.

Si realiza cambios con frecuencia, mantenga una versión anterior del archivo de disco para probar la deserialización. Puede escribir pruebas unitarias para tratar de leer en el archivo anterior y ver si funciona o si es totalmente incompatible.

Una advertencia, personalmente he experimentado el dolor que está trabajando con las clases Serializable originalmente pensadas para el almacenamiento a largo plazo que fueron diseñadas incorrectamente. Por ejemplo, almacenar elementos de la GUI en el disco en lugar de crearlos cuando sea necesario. Pregúntese si Serializable es realmente la mejor manera de guardar sus datos.

+0

+1 para señalar los problemas con Serializable para almacenar datos, especialmente cuando se usa sus propias clases (las que están en el JDK en sí son al menos lo suficientemente estables). – Thilo

+0

'... cambios incompatibles, que pueden dar como resultado excepciones de tiempo de ejecución' - necesita aclarar esto. Obtienes IOExceptions, no RuntimeExceptions. – EJP

+0

@EJP Tienes razón, podría haber formulado eso mejor. Obtendrá una IOEXception/en tiempo de ejecución/es lo que quise indicar con eso: su IDE o compilador no lo avisará con anticipación. –

16

El mantra frecuentemente repetido acerca de cambiar el serialVersionUID cada vez que cambia la clase es completo y totalmente absurdo. Ver this Sun article que republicaron en su sitio y que se migró a Oracle Technology Network después de la adquisición.

Debe cambiar el serialVersionUIDúnica cuando deliberadamente quiere romper la compatibilidad con todos los serializaciones existentes, por ejemplo, cuando los cambios en su clase lo hará de manera semánticamente diferente que no tiene otra opción - en cuyo caso se debe realmente piense varias veces sobre qué es lo que realmente está haciendo.

En todos los demás casos, deberá busto de su caldera de tratar de utilizar personalizados readObject()/writeObject() y/o writeReplace()/readResolve() métodos y/o serialFields anotaciones para que pueda seguir leyendo los objetos de esas serializaciones existentes. Una vez que rompes eso, tendrás un gran dolor de cabeza, de hecho una pesadilla.

+0

La URL no está disponible. ¿Puedes actualizarlo? –

+1

Esta respuesta podría mejorarse indicando exactamente con qué está en desacuerdo o con lo que cree que defiende su artículo vinculado. Al leer el artículo, no puedo ver con qué está "en desacuerdo" Sun. – DavidS

+0

qué sucede si agregué un nuevo campo a una clase. Este cambio aún es compatible: no se lanzará ninguna excepción. Pero el campo no contendrá ninguna información, por lo que semánticamente es incompatible. ¿Debería aumentar el UID en este caso? – damluar

-1

Es posible ajustar serialiVersionUID al mismo valor para la vida de la clase. (No siempre es una buena idea) Nota: puede implementar su propia estrategia de verificación de versión de serialización con readObject/writeObject si lo necesita y no modifica el UID.

La única vez que DEBE cambiarlo es si ya ha serializado algunos datos en un archivo y desea leerlos. Si ha cambiado por alguna razón, DEBE establecer el serialiVersionUID en la versión del archivo para tener la esperanza de poder leer los datos.

+0

Eso es más bien una indicación de que no debería haberlo cambiado en primer lugar. – EJP

Cuestiones relacionadas