generar java serialization code-generation serialversionuid

java - ¿Por qué generar un serialVersionUID largo en lugar de un simple 1L?



generar serialversionuid netbeans (10)

Cuando la clase implementa Serializable en Eclipse, tengo dos opciones: agregar el serialVersionUID(1L) predeterminado serialVersionUID(1L) o el serialVersionUID(3567653491060394677L) generado serialVersionUID(3567653491060394677L) . Creo que el primero es más genial, pero muchas veces vi a personas que usan la segunda opción. ¿Hay alguna razón para generar long serialVersionUID ?


Absolutamente debe crear un serialVersionUID cada vez que defina una clase que implementa java.io.Serializable . Si no lo haces, se creará uno automáticamente, pero esto es malo. El serialVersionUID generado automáticamente se basa en las firmas de métodos 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:

  1. Cree la primera versión de su clase, sin definir el serialVersionUID.
  2. Serializa una instancia de tu clase a un almacén persistente; un serialVersionUID se genera automáticamente para usted.
  3. Modifique su clase para agregar un nuevo método y vuelva a implementar su aplicación.
  4. Intente deserializar la instancia que se serializó en el paso 2, pero ahora falla (cuando debería tener éxito), ya que tiene un serialVersionUID diferente generado automáticamente.

Bueno, serialVersionUID es una excepción a la regla de que "los campos estáticos no se serializan". ObjectOutputStream escribe cada vez el valor de serialVersionUID en el flujo de salida. ObjectInputStream lo lee de nuevo y si el valor leído de la secuencia no concuerda con el valor serialVersionUID en la versión actual de la clase, entonces lanza 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 en base a los campos declarados en la clase.


Cuando usa serialVersionUID (1L) en lugar de generar serialVersionUID (3567653491060394677L) está diciendo algo.

Usted está diciendo que está 100% seguro de que ningún sistema que toque esta clase tendrá una versión serializada incompatible de esta clase con un número de versión de 1.

Si se le ocurre alguna excusa para que el historial de la versión serializada sea desconocido, puede ser difícil de decir con confianza. En su vida, una clase exitosa será mantenida por muchas personas, vivirá en muchos proyectos y residirá en muchos sistemas.

Puedes agonizarte por eso. O puedes jugar a la lotería esperando perder. Si generas la versión, tienes una pequeña posibilidad de que las cosas salgan mal. Si asume que "Hey, apuesto a que nadie usó 1 todavía", sus probabilidades son más grandes que pequeñas. Es precisamente porque todos pensamos que 0 y 1 son geniales porque tienes mayores probabilidades de golpearlos.

-

Cuando genera serialVersionUID (3567653491060394677L) en lugar de usar serialVersionUID (1L) está diciendo algo.

Está diciendo que la gente puede haber creado o generado manualmente otros números de versión a lo largo del historial de esta clase y no le importa porque los Longs son 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 donde ha existido o existirá alguna vez, se arriesga. Si tiene tiempo para asegurarse al 100% de que 1 es AOK, hágalo. Si eso es demasiado trabajo, sigue adelante y genera ciegamente el número. Es más probable que gane la lotería que que salga mal. Si es así, avísame y te compraré una cerveza.

Con toda esta charla sobre cómo jugar a la lotería, es posible que le haya dado la impresión de que serialVersionUID se genera de forma aleatoria. De hecho, siempre que el rango de números se distribuya uniformemente sobre cada valor posible de un Largo que 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 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. Así que buena suerte sacándome una cerveza.

Sin embargo, incluso si la clase solo vivirá en un sistema y una base de código, pensar que aumentar el número a mano no le da ninguna posibilidad de colisiones significa que no entiende a los humanos. :)


El propósito de la 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 un ID que sea único para una determinada versión de una clase, que luego se modifica cuando se agregan nuevos detalles a la clase, como un nuevo campo, que afectaría la estructura del objeto serializado.

Usar siempre la misma ID, como 1L significa que en el futuro, si se cambia la definición de la clase lo que causa cambios en la estructura del objeto serializado, habrá una buena probabilidad de que surjan problemas al intentar deserializar un objeto.

Si se omite el ID, Java realmente calculará el ID para usted según 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 tratan sobre la serialización y el control de versiones de las clases:


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 deberá tener cuidado de que si cambia la clase (agregar / eliminar campos) también actualice la número de serie.

Si no tiene que ser compatible con los flujos de bits existentes, solo puede poner 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.


La razón principal de la generada sería hacerla compatible con una versión existente de la clase que ya tiene copias persistentes.


Para agregar a la respuesta de @David Schmitts, como regla general, siempre usaría el valor predeterminado de 1L de convención. Solo tuve que regresar y cambiar algunas de ellas unas cuantas veces, pero sabía que cuando realizaba el cambio y actualizaba el número predeterminado cada vez.

En mi empresa 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 en la que trabaja, use el valor predeterminado, a menos que piense que cambiará constantemente la estructura de sus clases en serie por algún motivo.


Por lo que puedo decir, eso sería solo por compatibilidad con versiones anteriores. Esto solo sería útil si olvidó usar un serialVersionUID antes, y luego realizó un cambio que sabe que debería ser compatible pero que hace que se rompa la serialización.

Consulte la especificación de serialización de Java para más detalles.


Porque en muchos casos la identificación por defecto no es única. Por eso creamos id para hacer un concepto único.


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 las versiones anteriores de serie pero cambia el hash, entonces necesita usar el serialVersionUID de número muy grande generado (o el número "esperado" del mensaje de error) . De lo contrario, si está realizando un seguimiento de todo usted mismo, 0, 1, 2 ... es mejor.