Cuando la clase implementa Serializable en Eclipse, tengo dos opciones: agregar predeterminado serialVersionUID(1L)
o generado serialVersionUID(3567653491060394677L)
. Creo que el primero es más genial, pero muchas veces vi gente usando la segunda opción. ¿Hay alguna razón para generar long serialVersionUID
?
java
serialization
code-generation
serialversionuid
Adaptador IA
fuente
fuente
0L
solo lo usa inicialmente.Respuestas:
Por lo que puedo decir, eso sería solo por compatibilidad con versiones anteriores. Esto solo sería útil si descuidaste usar un serialVersionUID antes y luego hiciste un cambio que sabes que debería ser compatible, pero que hace que la serialización se rompa.
Consulte las especificaciones de serialización de Java para más detalles.
fuente
El propósito del UID de la versión de serialización es hacer un seguimiento de las diferentes versiones de una clase para realizar una serialización válida de objetos.
La idea es generar una ID que sea única para una determinada versión de una clase, que luego se cambia cuando se agregan nuevos detalles a la clase, como un nuevo campo, que afectaría la estructura del objeto serializado.
Siempre usando la misma ID, como por ejemplo
1L
, en el futuro, si se cambia la definición de clase que causa cambios en la estructura del objeto serializado, habrá una buena posibilidad de que surjan problemas al intentar deserializar un objeto.Si se omite la ID, Java realmente calculará la ID para usted en función de los campos del objeto, pero creo que es un proceso costoso, por lo que proporcionar uno manualmente mejorará el rendimiento.
Aquí hay un par de enlaces a artículos que analizan la serialización y el control de versiones de las clases:
fuente
Note - It is strongly recommended that all serializable classes explicitly declare serialVersionUID values, since the default serialVersionUID computation is highly sensitive to class details that may vary depending on compiler implementations, and can thus result in unexpected serialVersionUID conflicts during deserialization, causing deserialization to fail.
El comentario anterior se tomó de Java Object Serialization Specification versión 6.0La razón principal para la generada sería hacerla compatible con una versión existente de la clase que ya tiene copias persistentes.
fuente
El valor predeterminado "largo" de
serialVersionUID
es el valor predeterminado definido por la Especificación de serialización de Java , calculado a partir del comportamiento de serialización predeterminado.Entonces, si agrega el número de versión predeterminado, su clase se (des) serializará más rápido siempre que nada haya cambiado estructuralmente, pero tendrá que tener cuidado de que si cambia la clase (agregar / eliminar campos) también actualice el número de serie.
Si no tiene que ser compatible con las secuencias de bits existentes, simplemente puede colocar
1L
allí e incrementar la versión según sea necesario cuando algo cambie. Es decir, cuando la versión de serialización predeterminada de la clase modificada sería diferente de la versión predeterminada de la clase anterior.fuente
Absolutamente debe crear un serialVersionUID cada vez que defina una clase que implemente
java.io.Serializable
. Si no lo hace, se creará uno para usted automáticamente, pero esto es malo. El serialVersionUID generado automáticamente se basa en las firmas de método de su clase, por lo que si cambia su clase en el futuro para agregar un método (por ejemplo), la deserialización de las versiones "antiguas" de la clase fallará. Esto es lo que puede pasar:fuente
Si no especifica un serialVersionUID, Java crea uno sobre la marcha. El serialVersionUID generado es ese número. Si cambia algo en su clase que realmente no hace que su clase sea incompatible con versiones anteriores serializadas pero cambia el hash, entonces debe usar el número de serie serialVersionUID generado (o el número "esperado" del mensaje de error) . De lo contrario, si realiza un seguimiento de todo usted mismo, 0, 1, 2 ... es mejor.
fuente
Cuando usa serialVersionUID (1L) en lugar de generar serialVersionUID (3567653491060394677L) está diciendo algo.
Está diciendo que está 100% seguro de que ningún sistema tocará esta clase que tenga una versión serializada incompatible de esta clase con un número de versión 1.
Si puede pensar en alguna excusa para que su historial de versiones en serie sea desconocido, eso podría ser difícil de decir con confianza. En su vida, muchas personas mantendrán una clase exitosa, vivirán en muchos proyectos y residirán en muchos sistemas.
Puedes agonizar por eso. O puedes jugar a la lotería con la esperanza de perder. Si genera la versión, tiene una pequeña posibilidad de que las cosas salgan mal. Si asumes "Hey, apuesto a que nadie usó 1 todavía", tus probabilidades son mayores que pequeñas. Precisamente porque todos pensamos que 0 y 1 son geniales, tiene mayores probabilidades de alcanzarlos.
-
Cuando genera serialVersionUID (3567653491060394677L) en lugar de usar serialVersionUID (1L), está diciendo algo.
Está diciendo que las personas pueden haber creado o generado manualmente otros números de versión a lo largo del historial de esta clase y no le importa porque Longs está volviendo grandes números.
De cualquier manera, a menos que conozca perfectamente el historial de números de versión utilizados al serializar la clase en todo el universo de dónde ha existido o existirá alguna vez, se está arriesgando. Si tienes tiempo para asegurarte al 100% de que 1 es AOK, hazlo. Si eso es demasiado trabajo, adelante y genera el número a ciegas. Es más probable que ganes la lotería que que salga mal. Si es así, avísame y te compraré una cerveza.
Con toda esta charla sobre jugar a la lotería, puedo haberte dado la impresión de que serialVersionUID se genera aleatoriamente. De hecho, siempre y cuando el rango de números se distribuya uniformemente sobre cada valor posible de un Long, estaría bien. Sin embargo, en realidad se hace de esta manera:
http://docs.oracle.com/javase/6/docs/platform/serialization/spec/class.html#4100
La única diferencia que obtienes con eso es que no necesitas una fuente aleatoria. Estás usando los cambios en la clase misma para cambiar el resultado. Pero de acuerdo con el principio del casillero, todavía existe la posibilidad de que pueda salir mal y tener una colisión. Es increíblemente improbable. Buena suerte sacando una cerveza de mí.
Sin embargo, incluso si la clase solo vivirá en un sistema y una base de código, pensar que incrementar el número a mano te da cero posibilidades de colisiones solo significa que no entiendes a los humanos. :)
fuente
Bueno, serialVersionUID es una excepción a la regla de que "los campos estáticos no se serializan". ObjectOutputStream escribe cada vez que el valor de serialVersionUID en la secuencia de salida. ObjectInputStream lo lee de nuevo y si el valor leído de la secuencia no está de acuerdo con el valor serialVersionUID en la versión actual de la clase, arroja la InvalidClassException. Además, si no hay un serialVersionUID declarado oficialmente en la clase para ser serializado, el compilador lo agrega automáticamente con un valor generado basado en los campos declarados en la clase.
fuente
Porque en muchos casos la identificación predeterminada no es única. entonces creamos id para hacer un concepto único.
fuente
Para agregar a la respuesta de @David Schmitts, como regla general, siempre usaría el 1L predeterminado fuera de convención. Solo tuve que regresar y cambiar algunos de ellos algunas veces, pero lo sabía cuando hice el cambio y actualicé el número predeterminado por uno cada vez.
En mi compañía actual requieren el número generado automáticamente, así que lo uso para convenciones, pero prefiero el predeterminado. Mi opinión es que, si no es una convención donde trabajas, usa el predeterminado, a menos que pienses que cambiarás constantemente la estructura de tus clases serializadas por alguna razón.
fuente
El propósito del UID de la versión de serialización es hacer un seguimiento de las diferentes versiones de una clase para realizar una serialización válida de objetos.
La idea es generar una ID que sea única para una determinada versión de una clase, que luego se cambia cuando se agregan nuevos detalles a la clase, como un nuevo campo, que afectaría la estructura del objeto serializado.
Una explicación simple:
¿Estás serializando datos?
La serialización consiste básicamente en escribir datos de clase en un archivo / secuencia / etc. La deserialización es leer esos datos nuevamente en una clase.
¿Pretendes entrar en producción?
Si solo está probando algo con datos falsos o sin importancia, no se preocupe por ello (a menos que esté probando la serialización directamente).
¿Es esta la primera versión?
Si es así, establezca serialVersionUID = 1L.
¿Es esta la segunda, tercera, etc. versión prod?
Ahora debe preocuparse por serialVersionUID, y debe analizarlo en profundidad.
Básicamente, si no actualiza la versión correctamente cuando actualiza una clase que necesita escribir / leer, recibirá un error cuando intente leer datos antiguos.
fuente