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

Eclipse emite advertencias cuando un serialVersionUID no se encuentra.

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

¿Qué es? serialVersionUID ¿y porque es importante? Muestre un ejemplo donde falta serialVersionUID causará un problema.

preguntado el 13 de noviembre de 08 a las 00:11

Encuentre una buena práctica sobre serialversionUID; dzone.com/articles/what-is-serialversionuid -

26 Respuestas

Los documentos para java.io.Serializable probablemente sean una explicación tan buena como la que obtendrás:

El tiempo de ejecución de serialización asocia con cada clase serializable un número de versión, llamado serialVersionUID, que se utiliza 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 serialVersionUID que el de la clase del remitente correspondiente, entonces la deserialización resultará en una InvalidClassException. Una clase serializable puede declarar su propia serialVersionUID explícitamente declarando un campo llamado serialVersionUID que 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 un serialVersionUID, entonces el tiempo de ejecución de serialización calculará un valor predeterminado serialVersionUID valor para esa clase en función de varios aspectos de la clase, como se describe en la Especificación de serialización de objetos de Java (TM). Sin embargo lo és muy recomendado que todas las clases serializables declaran explícitamente serialVersionUID valores, ya que el valor predeterminado serialVersionUID El cálculo es muy sensible a los detalles de la clase que pueden variar dependiendo de las implementaciones del compilador y, por lo tanto, pueden resultar en resultados inesperados. InvalidClassExceptions durante la deserialización. Por tanto, para garantizar una coherencia serialVersionUID valor en diferentes implementaciones del compilador de Java, una clase serializable debe declarar un explícito serialVersionUID valor. También se recomienda encarecidamente que serialVersionUID las declaraciones usan el modificador privado siempre que sea posible, ya que tales declaraciones se aplican solo a la clase que declara inmediatamente - serialVersionUID los campos no son útiles como miembros heredados.

Respondido el 14 de enero de 21 a las 22:01

Entonces, lo que está diciendo esencialmente es que si un usuario no entendió todo el material anterior, dicho usuario no se molestaría en preocuparse por la serialización. Creo que respondió el "¿cómo?" en lugar de explicar el "¿por qué?". Yo, por mi parte, no entiendo por qué me molesto con SerializableVersionUID. - Ziggy

El por qué está en el segundo párrafo: si no especifica explícitamente serialVersionUID, se genera un valor automáticamente, pero eso es frágil porque depende de la implementación del compilador. - Jon Skeet

¿Y por qué Eclipse dice que necesito "private static final long serialVersionUID = 1L;" cuando extiendo la clase Exception? - John Merlino

@JohnMerlino: Bueno, no esperaría que te dijera necesitas uno - pero puede ser sugerencia one para ayudarle a serializar las excepciones correctamente. Si no los va a serializar, realmente no necesita la constante. - Jon Skeet

@JohnMerlino, para responder al por qué parte de su pregunta: Implementa la excepción Serializable y eclipse advierte que no ha establecido un serialVersionUID, lo cual sería una buena idea (si no desea serializar la clase) para evitar los problemas que describe la publicación de JonSkeet. - zpon

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 ignorar esto.

Si realmente está usando la serialización, solo importa si planea almacenar y recuperar objetos usando la serialización directamente. La serialVersionUID representa la versión de su clase, y debe incrementarla si la versión actual de su clase no es compatible con la versión anterior.

La mayoría de las veces, probablemente no utilizará la serialización directamente. Si este es el caso, genere una SerialVersionUID haciendo clic en la opción de solución rápida y no se preocupe.

Respondido 24 Feb 19, 10:02

Yo diría que si no está usando la serialización para el almacenamiento permanente, debería usar @SuppressWarnings en lugar de agregar un valor. Desordena menos la clase y preserva la capacidad del mecanismo serialVersionUID para protegerlo de cambios incompatibles. - Tom Anderson

No veo cómo agregar una línea (anotación @SuppressWarnings) en lugar de otra línea (identificación serializable) "desordena menos la clase". Y si no está utilizando la serialización para el almacenamiento permanente, ¿por qué no utilizaría simplemente "1"? De todos modos, no le importaría la identificación generada automáticamente en ese caso. - MetroidFan2002

@ MetroidFan2002: Creo que el punto de @ TomAnderson de serialVersionUID protegerte de cambios incompatibles es válido. Utilizando @SuppressWarnings documenta mejor la intención si no desea utilizar la clase para almacenamiento permanente. - AbdullahC

"Debería incrementarlo si la versión actual de su clase no es compatible con la versión anterior:" Primero debería explorar el amplio soporte de versiones de objetos de Serialización, (a) para asegurarse de que la clase ahora sea realmente incompatible con la serialización, que según la especificación es bastante difícil de lograr; (b) para probar un esquema como los métodos read / writeObject () personalizados, métodos readResolve / writeReplace (), declaraciones serializableFields, etc., para asegurarse de que el flujo siga siendo compatible. Cambiando el real serialVersionUID es un último recurso, un consejo de desesperación. - user207421

El incremento de @EJP de serialVersionUID entra en escena cuando el autor inicial de la clase se ha introducido explícitamente. Yo diría que jvm generó una identificación de serie, debería estar bien. esto es lo mejor https://www.youtube.com/watch?v=xB-eutXNUMXJtA&feature=youtu.be que vi en la serialización. - sobreintercambio

No puedo dejar pasar esta oportunidad de conectar el libro de Josh Bloch Java eficaz (2da edición). El capítulo 11 es un recurso indispensable sobre la serialización de Java.

Según Josh, el UID generado automáticamente se genera en función de un nombre de clase, interfaces implementadas y todos los miembros públicos y protegidos. Cambiar cualquiera de estos de alguna manera cambiará el serialVersionUID. Por lo tanto, no necesita meterse con ellos solo si está seguro de que no se serializará más de una versión de la clase (ya sea entre procesos o recuperada 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 el serialVersionUID al los ancianos class, y establezca explícitamente eso en la nueva clase. (Dependiendo de sus cambios, es posible que deba implementar también la serialización personalizada agregando writeObject y readObject métodos - ver Serializable javadoc o el mencionado capítulo 11.)

Respondido 29 Oct 15, 16:10

Entonces, ¿uno podría molestarse con SerializableVersionUID si estuviera preocupado por la compatibilidad con versiones antiguas de una clase? - Ziggy

Sí, en caso de que la versión más reciente cambie algún miembro público a protegido, el SerializableVersionUID predeterminado será diferente y generará una InvalidClassExceptions. - Chander Shivdasani

Nombre de clase, interfaces implementadas, todos los métodos públicos y protegidos, TODAS las variables de instancia. - Achow

Vale la pena señalar que Joshua Bloch advierte que para cada Clase serializable, vale la pena especificar el uid de la versión serial. Cita del capítulo 11: Independientemente de la forma serializada que elija, declare un UID de versión serial explícito en cada clase serializable que escriba. Esto elimina el UID de la versión serial como una fuente potencial de incompatibilidad (ítem 74). También hay un pequeño beneficio de rendimiento. Si no se proporciona un UID de versión en serie, se requiere un cálculo costoso para generar uno en tiempo de ejecución. - Ashutosh Jindal

Parece relevante. Un enlace a un par de enfoques para generar el UID de la versión en serie mediante IDE: mkyong.com/java/how-to-generate-serialversionuid - Ben

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 supiera, hay muchas otras advertencias que puede habilitar en esta sección (o incluso tener algunas reportadas como errores), muchas son muy útiles:

  • Posibles problemas de programación: posible asignación booleana accidental
  • Posibles problemas de programación: acceso de 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.

respondido 13 nov., 08:04

voto positivo, pero solo porque el póster original no parece estar serializando nada. Si el cartel dijera "estoy publicando esta cosa y ...", entonces obtendría un voto en contra: P - John Gardner

Es cierto, estaba asumiendo que el interrogador simplemente no quería ser advertido. mate b

@Gardner -> ¡de acuerdo! Pero el interrogador también quiere saber por qué es posible que no quiera ser advertido. - Ziggy

El interrogador obviamente se preocupa por la razón por la que debería haber un UID. Así que simplemente decirle que ignore la advertencia debería ser rechazado. - cinqS

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 un serialVersionUID de 0 y colóquelo con cada cambio estructural en su clase que altere los datos serializados (agregando o eliminando campos no transitorios).

El mecanismo de deserialización integrado (in.defaultReadObject()) se negará a deserializar las versiones anteriores de los datos. Pero si quieres puedes definir el tuyo readObject ()-función que puede leer datos antiguos. Este código personalizado puede luego verificar el serialVersionUID para saber en qué versión están 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 en, por ejemplo, una 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. Solo le preocupa asegurarse de que las bases de código que se están comunicando tengan las mismas versiones de las clases relevantes. Para facilitar dicho control, debe mantener el serialVersionUID como antes y no olvide actualizarlo cuando haga cambios en sus clases.

Si olvida actualizar el campo, puede terminar con dos versiones diferentes de una clase con una estructura diferente pero con la misma serialVersionUID. Si esto sucede, el mecanismo predeterminado (in.defaultReadObject()) no detectará ninguna diferencia e intentará deserializar los datos incompatibles. Ahora puede terminar con un error críptico en tiempo de ejecución o una falla silenciosa (campos nulos). Estos tipos 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 configurar el serialVersionUID a mano. En su lugar, se generará un hash de la estructura de la clase en tiempo de compilación y se usará como id. Este mecanismo se asegurará de que nunca tenga diferentes estructuras de clases con la misma identificación, por lo que no obtendrá estas fallas de serialización en tiempo de ejecución difíciles de rastrear mencionadas anteriormente.

Pero hay una parte trasera de la estrategia de identificación generada automáticamente. Es decir, que los identificadores generados para la misma clase pueden diferir entre compiladores (como lo mencionó Jon Skeet anteriormente). Por lo tanto, 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.

Respondido 03 Oct 12, 10:10

Agregar o eliminar campos no transitorios no hace que la serialización de clases sea incompatible. Por lo tanto, no hay ninguna razón para "tropezar" con tales cambios. - user207421

@EJP: ¿Eh? Agregar datos definitivamente cambia los datos de serialización en mi mundo. - Alexander Torstling

@AlexanderTorstling Lea lo que escribí. No dije que no 'cambia los datos de serialización'. Dije que 'no hace que la serialización de clases sea incompatible'. No es lo mismo. Debe leer el capítulo Versiones de la Especificación de serialización de objetos. - user207421

@EJP: Me doy cuenta de que agregar un campo no transitorio no significa necesariamente que haga que la serialización de la clase sea incompatible, pero es un cambio estructural que altera los datos serializados y, por lo general, desea aumentar la versión al hacerlo, a menos que manejar la compatibilidad con versiones anteriores, que también expliqué más adelante en la publicación. ¿Cuál es su punto exactamente? - Alexander Torstling

Mi punto sigue siendo exactamente lo que dije. Agregar o eliminar campos no transitorios no hace que la clase sea incompatible con la serialización. Por lo tanto, no es necesario que agregue serialVersionUID cada vez que lo haga. - user207421

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

SerialVersionUID es un identificador único para cada clase, JVM lo usa para comparar las versiones de la clase asegurándose de que la misma clase se usó durante la serialización y se carga durante la deserialización.

Especificar uno da más control, aunque JVM genera uno si no lo especifica. El valor generado puede diferir entre diferentes compiladores. Además, a veces solo desea, por alguna razón, prohibir la deserialización de objetos serializados antiguos [backward incompatibility], y en este caso solo tienes que cambiar el serialVersionUID.

La javadocs para Serializable dices:

El cálculo de serialVersionUID predeterminado es muy sensible a los detalles de la clase que pueden variar según las implementaciones del compilador y, por lo tanto, puede resultar en InvalidClassExceptions durante la deserialización.

Por lo tanto, debe declarar serialVersionUID porque nos da más control.

Este artículo tiene algunos buenos puntos sobre el tema.

Respondido 08 Jul 18, 10:07

@Vinothbabu pero serialVersionUID es estático, por lo que las variables estáticas no se pueden serializar. entonces, ¿cómo es que jvm verificará la versión, sin saber cuál es la versión del objeto de deserialización? Kranthi Sama

Lo único que no se menciona en esta respuesta es que puede causar consecuencias no deseadas al incluir ciegamente serialVersionUID sin saber por qué. El comentario de Tom Anderson sobre la respuesta de MetroidFan2002 aborda esto: "Yo diría que si no está utilizando la serialización para el almacenamiento permanente, debería usar @SuppressWarnings en lugar de agregar un valor. Desordena menos la clase y preserva la capacidad de la mecanismo serialVersionUID para protegerlo de cambios incompatibles ". - Kirby

serialVersionUID is no un 'identificador único para cada clase'. El nombre de la clase completamente calificado es ese. Es un versión indicador. - user207421

La pregunta original ha pedido 'por qué es importante' y 'ejemplo' donde esto Serial Version ID sería útil. Bueno, he encontrado uno.

Digamos que creas un Car class, instanciarlo y escribirlo en un flujo de objeto. El objeto de automóvil aplanado permanece en el sistema de archivos durante algún tiempo. Mientras tanto, si el Car La clase se modifica agregando un nuevo campo. Más adelante, cuando intente leer (es decir, deserializar) el Car objeto, obtienes el java.io.InvalidClassException - porque todas las clases serializables reciben automáticamente un identificador único. Esta excepción se lanza cuando el identificador de la clase no es igual al identificador del objeto aplanado. Si realmente lo piensa, se lanza la excepción debido a la adición del nuevo campo. Puede evitar que se produzca esta excepción controlando el control de versiones usted mismo declarando un serialVersionUID explícito. También hay un pequeño beneficio de rendimiento al declarar explícitamente su serialVersionUID (porque no tiene que ser calculado). Por lo tanto, es una buena práctica agregar su propio serialVersionUID a sus clases serializables tan pronto como las cree, como se muestra a continuación:

public class Car {
    static final long serialVersionUID = 1L; //assign a long value
}

Respondido el 14 de enero de 19 a las 17:01

Y se debe asignar un número largo aleatorio, no 1L, a cada UID. - Abbas

@abbas 'Uno debería' hacer eso, ¿por qué? Explique qué diferencia hace. - user207421

Como dice el nombre, representa la versión de la clase que se utilizó para serializar el objeto. Si le asigna el mismo número cada vez, no podrá encontrar la clase correcta para deserializarlo. Por lo tanto, siempre que realice un cambio en la clase, es mejor cambiar también la versión. - Abbas

@abbas, esta intención no choca con el uso de números naturales incrementales de 1 y así. - Vadzim

@BillK, pensé que la verificación de serialización está vinculada al par de classname y serialVersionUID. Por lo tanto, los diferentes esquemas de numeración de diferentes clases y bibliotecas no pueden interferir de ninguna manera. ¿O insinuó bibliotecas generadoras de código? - Vadzim

Primero necesito explicar qué es la serialización.

Publicación por entregas permite convertir un objeto en una secuencia, para enviar ese objeto a través de la red O Guardar en archivo O guardar en DB para uso de letras.

Hay algunas reglas para la serialización..

  • Un objeto es serializable solo si su clase o su superclase implementa la interfaz serializable

  • Un objeto es serializable (él mismo implementa la interfaz serializable) incluso si su superclase no lo es. Sin embargo, la primera superclase en la jerarquía de la clase serializable, que no implementa la interfaz serializable, DEBE tener un constructor sin argumentos. Si esto se viola, readObject () producirá una java.io.InvalidClassException en tiempo de ejecución

  • Todos los tipos primitivos son serializables.

  • Los campos transitorios (con modificador transitorio) NO se serializan (es decir, no se guardan ni se restauran). Una clase que implementa Serializable debe marcar campos transitorios de clases que no admiten la serialización (por ejemplo, un flujo de archivos).

  • Los campos estáticos (con modificador estático) no se serializan.

Cuando te Object está serializado, Java Runtime asocia el número de versión de serie, también conocido como serialVersionID.

Donde necesitamos serialVersionID:

Durante la deserialización para verificar que el remitente y el receptor sean compatibles con respecto a la serialización. Si el receptor cargó la clase con un serialVersionID entonces la deserialización terminará con InvalidClassCastException.
Una clase serializable puede declarar su propia serialVersionUID explícitamente declarando un campo llamado serialVersionUID que debe ser estático, final y de tipo largo.

Intentemos esto con un ejemplo.

import java.io.Serializable;

public class Employee implements Serializable {
    private static final long serialVersionUID = 1L;
    private String empname;
    private byte empage;

    public String getEmpName() {
        return name;
    }

    public void setEmpName(String empname) {
        this.empname = empname;
    }

    public byte getEmpAge() {
        return empage;
    }

    public void setEmpAge(byte empage) {
        this.empage = empage;
    }

    public String whoIsThis() {
        return getEmpName() + " is " + getEmpAge() + "years old";
    }
}

Crear objeto serializar

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;

public class Writer {
    public static void main(String[] args) throws IOException {
        Employee employee = new Employee();
        employee.setEmpName("Jagdish");
        employee.setEmpAge((byte) 30);

        FileOutputStream fout = new
                FileOutputStream("/users/Jagdish.vala/employee.obj");
        ObjectOutputStream oos = new ObjectOutputStream(fout);
        oos.writeObject(employee);
        oos.close();
        System.out.println("Process complete");
    }
}

Deserializar el objeto

import java.io.FileInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;

public class Reader {
    public static void main(String[] args) throws ClassNotFoundException, IOException {
        Employee employee = new Employee();
        FileInputStream fin = new FileInputStream("/users/Jagdish.vala/employee.obj");
        ObjectInputStream ois = new ObjectInputStream(fin);
        employee = (Employee) ois.readObject();
        ois.close();
        System.out.println(employee.whoIsThis());
    }
}

NOTA: Ahora cambie el serialVersionUID de la clase Empleado y guarde:

private static final long serialVersionUID = 4L;

Y ejecuta la clase Reader. No ejecutar la clase Writer y obtendrá la excepción.

Exception in thread "main" java.io.InvalidClassException: 
com.jagdish.vala.java.serialVersion.Employee; local class incompatible: 
stream classdesc serialVersionUID = 1, local class serialVersionUID = 4
at java.io.ObjectStreamClass.initNonProxy(ObjectStreamClass.java:616)
at java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:1623)
at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1518)
at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1774)
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1351)
at java.io.ObjectInputStream.readObject(ObjectInputStream.java:371)
at com.krishantha.sample.java.serialVersion.Reader.main(Reader.java:14)

Respondido el 22 de junio de 20 a las 13:06

Corríjame si me equivoco: la clase local es la que tiene / usa actualmente en la ruta de clase y la de flujo es la que usa otra parte (por ejemplo, un servidor que le está devolviendo una respuesta y ha serializado el respuesta). Puede encontrar esta situación cuando se está comunicando con un servidor que ha actualizado sus bibliotecas de terceros, pero usted (el cliente) no lo hizo. - Víctor

Si nunca necesitará serializar sus objetos en una matriz de bytes y enviarlos / almacenarlos, entonces no necesita preocuparse por eso. Si lo hace, debe considerar su serialVersionUID ya que el deserializador del objeto lo hará coincidir con la versión del objeto que tiene su cargador de clases. Lea más sobre esto en la Especificación del lenguaje Java.

Respondido 09 Jul 14, 22:07

Si no va a serializar los objetos, ¿por qué son serializables? - erickson

@erickson: la clase principal puede ser serializable, digamos, ArrayList, pero desea que su propio objeto (digamos, una lista de matriz modificada) lo use como base, pero nunca va a serializar la Colección que crea. - MetroidFan2002

No se menciona en ninguna parte de la Especificación del lenguaje Java. Se menciona en la Especificación de control de versiones de objetos. - user207421

Aquí está el enlace a Java 8 Especificación de versiones de objetos. - Albahaca bourque

Si recibe esta advertencia en una clase, nunca piensa en serializar y que no se declaró implements Serializable, a menudo se debe a que heredó de una superclase, que implementa Serializable. A menudo, sería mejor delegar en un objeto de este tipo en lugar de utilizar la herencia.

Entonces, en lugar de

public class MyExample extends ArrayList<String> {

    public MyExample() {
        super();
    }
    ...
}

do

public class MyExample {
    private List<String> myList;

    public MyExample() {
         this.myList = new ArrayList<String>();
    }
    ...
}

y en los métodos relevantes llamar myList.foo() en lugar de this.foo() (o super.foo()). (Esto no se ajusta a todos los casos, pero sigue siendo bastante frecuente).

A menudo veo personas que extienden JFrame o algo así, cuando en realidad solo necesitan delegar en esto. (Esto también ayuda a completar automáticamente en un IDE, ya que JFrame tiene cientos de métodos, que no necesita cuando desea llamar a los personalizados en su clase).

Un caso en el que la advertencia (o serialVersionUID) es inevitable es cuando se extiende desde AbstractAction, normalmente en una clase anónima, solo agregando el método actionPerformed. Creo que no debería haber una advertencia en este caso (ya que normalmente no puede serializar y deserializar de manera confiable tales clases anónimas de todos modos en diferentes versiones de su clase), pero no estoy seguro de cómo el compilador podría reconocer esto.

Respondido 03 Feb 11, 03:02

Creo que tiene razón en que la composición sobre la inercia tiene más sentido, especialmente cuando se habla de clases como ArrayList. Sin embargo, muchos marcos requieren que las personas se extiendan desde superclases abstractas que son serializables (como la clase ActionForm de Struts 1.2 o ExtensionFunctionDefinition de Saxon), en cuyo caso esta solución no es factible. Creo que tiene razón, sería bueno si la advertencia se ignorara en ciertos casos (como si se extendiera desde una clase serializable abstracta) - piepera

Seguramente si agrega una clase como miembro, en lugar de heredar de ella, tendrá que escribir un método contenedor para CADA método de la clase miembro que desea usar, lo que lo haría inviable en una gran cantidad de situaciones. . a menos que java tenga una función similar a la de perl __AUTOLOAD, que no conozco. - M_M

@M_M: cuando delegaría muchos métodos a su objeto envuelto, por supuesto, no sería apropiado usar la delegación. Pero supongo que este caso es una señal de un error de diseño: los usuarios de su clase (por ejemplo, "MainGui") no deberían necesitar llamar a muchos métodos del objeto envuelto (por ejemplo, JFrame). - Paŭlo Ebermann

Lo que no me gusta de la delegación es la necesidad de tener una referencia al delegado. Y cada referencia significa más memoria. Corrígeme si estoy equivocado. Si necesito una CustomizedArrayList de 100 objetos, entonces esto no importaría mucho, pero si necesito cientos de CustomizdeArrayLists de unos pocos objetos, entonces el uso de memoria aumenta significativamente. - WVrock

Throwable es serializable, y solo Throwable se puede lanzar, por lo que no es posible definir una excepción que no sea serializable. La delegación no es posible. - Phil

Para comprender la importancia del campo serialVersionUID, se debe comprender cómo funciona la serialización / deserialización.

Cuando se serializa un objeto de clase serializable, Java Runtime asocia un número de versión serial (llamado serialVersionUID) con este objeto serializado. En el momento en que deserializa este objeto serializado, Java Runtime hace coincidir el serialVersionUID del objeto serializado con el serialVersionUID de la clase. Si ambos son iguales, solo continúa con el proceso adicional de deserialización; de lo contrario, arroja InvalidClassException.

Entonces concluimos que para que el proceso de serialización / deserialización sea exitoso, el serialVersionUID del objeto serializado debe ser equivalente al serialVersionUID de la clase. En caso de que el programador especifique el valor serialVersionUID explícitamente en el programa, el mismo valor se asociará con el objeto serializado y la clase, independientemente de la plataforma de serialización y deserialización (por ejemplo, la serialización se puede realizar en una plataforma como Windows usando sun o MS JVM y deserialización pueden estar en diferentes plataformas Linux usando Zing JVM).

Pero en caso de que el programador no especifique serialVersionUID, mientras realiza Serialization \ DeSerialization de cualquier objeto, el tiempo de ejecución de Java utiliza su propio algoritmo para calcularlo. Este algoritmo de cálculo serialVersionUID varía de un JRE a otro. También es posible que el entorno donde se serializa el objeto esté usando un JRE (por ejemplo: SUN JVM) y el entorno donde ocurre la deserialización esté usando Linux Jvm (zing). En tales casos, el serialVersionUID asociado con el objeto serializado será diferente al serialVersionUID de la clase calculado en el entorno de deserialización. A su vez, la deserialización no tendrá éxito. Entonces, para evitar tales situaciones / problemas, el programador siempre debe especificar serialVersionUID de la clase Serializable.

contestado el 21 de mayo de 14 a las 01:05

El algoritmo no varía, pero está ligeramente subespecificado. - user207421

... el algoritmo no varía, pero está ligeramente subespecificado ... lo que significa que cualquier jvm puede variar ..... @ user207421 - AnthonyJClink

En cuanto a un ejemplo en el que el serialVersionUID que falta podría causar un problema:

Estoy trabajando en esta aplicación Java EE que se compone de un módulo web que usa un EJB módulo. El módulo web llama al EJB módulo de forma remota y pasa un POJO que implementa Serializable como argumento

Este patrón de POJO's La clase se empaquetó dentro del jar EJB y dentro de su propio jar en WEB-INF / lib del módulo web. En realidad, son la misma clase, pero cuando empaqueto el módulo EJB, descomprimo el frasco de este POJO para empaquetarlo junto con el módulo EJB.

La llamada al EJB estaba fallando con la excepción a continuación porque no había declarado su serialVersionUID:

Caused by: java.io.IOException: Mismatched serialization UIDs : Source
 (Rep.
 IDRMI:com.hordine.pedra.softbudget.domain.Budget:5CF7CE11E6810A36:04A3FEBED5DA4588)
 = 04A3FEBED5DA4588 whereas Target (Rep. ID RMI:com.hordine.pedra.softbudget.domain.Budget:7AF5ED7A7CFDFF31:6227F23FA74A9A52)
 = 6227F23FA74A9A52

Respondido el 19 de diciembre de 13 a las 22:12

No se moleste, el cálculo predeterminado es realmente bueno y suficiente para el 99,9999% de los casos. Y si tiene problemas, puede, como ya se dijo, introducir UID cuando surja la necesidad (lo cual es muy poco probable)

Respondido 29 Abr '12, 19:04

Basura. Es adecuado en el caso de que la clase no haya cambiado. No tiene pruebas que respalden el '99.9999 .XNUMX% '. - user207421

El problema no es que no sea "bueno", pero no se garantiza que sea consistente en diferentes versiones. - Dorian Gray

Generalmente uso serialVersionUID en un contexto: cuando sepa que saldrá del contexto de la máquina virtual Java.

Sabría esto cuando lo use ObjectInputStream y ObjectOutputStream para mi aplicación o si conozco una biblioteca / marco que uso, lo usaré. SerialVersionID asegura que diferentes máquinas virtuales Java de diferentes versiones o proveedores interactuarán correctamente o si se almacenan y recuperan fuera de la máquina virtual, por ejemplo HttpSession los datos de la sesión pueden permanecer incluso durante el reinicio y la actualización del servidor de aplicaciones.

Para todos los demás casos, uso

@SuppressWarnings("serial")

ya que la mayoría de las veces el valor predeterminado serialVersionUID es suficiente. Esto incluye Exception, HttpServlet.

respondido 04 mar '14, 20:03

No incluye HttpServlet en contenedores donde se pueden intercambiar, o Excepción en RMI, por ejemplo. - user207421

Los datos de campo representan cierta información almacenada en la clase. La clase implementa la Serializable interfaz, por lo que eclipse se ofreció automáticamente a declarar el serialVersionUID campo. Comencemos con el valor 1 establecido allí.

Si no quiere que llegue esa advertencia, use esto:

@SuppressWarnings("serial")

respondido 13 mar '13, 18:03

Sería bueno si CheckStyle pudiera verificar que el serialVersionUID en una clase que implementa Serializable tiene un buen valor, es decir, que coincide con lo que produciría el generador de ID de versión serial. Si tiene un proyecto con muchos DTO serializables, por ejemplo, recordar eliminar el serialVersionUID existente y regenerarlo es una molestia, y actualmente la única forma (que yo sepa) de verificar esto es regenerar para cada clase y comparar con el viejo. Esto es muy, muy doloroso.

Respondido el 03 de diciembre de 08 a las 17:12

Si establece el serialVersionUID siempre en el mismo valor que produciría el generador, realmente no lo necesita en absoluto. Después de todo, su razón de ser es permanecer igual después de los cambios, cuando la clase sigue siendo compatible. - Paŭlo Ebermann

La razón es que diferentes compiladores obtienen el mismo valor para la misma clase. Como se explica en los javadocs (también respondido anteriormente), la versión generada es frágil y puede variar incluso cuando la clase se puede deserializar correctamente. Siempre que ejecute esta prueba en el mismo compilador cada vez, debería ser seguro. Dios te ayude si actualizas el jdk y aparece una nueva regla, aunque tu código no haya cambiado. - Andrew Backer

No es necesario que coincida con lo serialver produciría. -1 - user207421

En general, no es necesario en absoluto. El caso de @ AndrewBacker requeriría dos compiladores diferentes en el mismo archivo .java con ambas versiones de los archivos .class comunicándose entre sí; la mayoría de las veces, solo crea la clase y la distribuye. Si ese es el caso, entonces no tener un SUID funcionaría bien. - Bill K

Las personas que realmente usan la serialización para fines de almacenamiento / recuperación generalmente establecerán el serialVersionUID a 1. Si una versión más nueva de la clase es incompatible, pero aún requiere poder manejar los datos antiguos, incrementa el número de versión y agrega un código especial para manejar formatos más antiguos. Lloro cada vez que veo un serialVersionUID mayor que 1 dígito, ya sea porque era un número aleatorio (inútil) o porque la clase aparentemente necesita tratar con más de 10 versiones diferentes. - john16384

SerialVersionUID se utiliza para el control de versiones del objeto. también puede especificar serialVersionUID en su archivo de clase. La consecuencia de no especificar serialVersionUID es que cuando agrega o modifica cualquier campo en la clase, la clase ya serializada no podrá recuperarse porque serialVersionUID generado para la nueva clase y para el antiguo objeto serializado será diferente. El proceso de serialización de Java se basa en el serialVersionUID correcto para recuperar el estado del objeto serializado y arroja java.io.InvalidClassException en caso de que no coincida serialVersionUID

Lee mas: http://javarevisited.blogspot.com/2011/04/top-10-java-serialization-interview.html#ixzz3VQxnpOPZ

respondido 26 mar '15, 00:03

¿Por qué utilizar SerialVersionUID dentro Serializable clase en Java?

Durante serialization, Java runtime crea un número de versión para una clase, para que pueda deserializarla más tarde. Este número de versión se conoce como SerialVersionUID en Java

SerialVersionUID se utiliza para versionar datos serializados. Solo puede deserializar una clase si es SerialVersionUID coincide con la instancia serializada. Cuando no declaramos SerialVersionUID en nuestra clase, el tiempo de ejecución de Java lo genera para nosotros, pero no se recomienda. Se recomienda declarar SerialVersionUID as private static final long variable para evitar el mecanismo predeterminado.

Cuando declaras una clase como Serializable mediante la implementación de la interfaz de marcador java.io.Serializable, El tiempo de ejecución de Java persiste la instancia de esa clase en el disco mediante el mecanismo de serialización predeterminado, siempre que no haya personalizado el proceso usando Externalizable de la interfaz del.

véase también Por que usar SerialVersionUID dentro de la clase Serializable en Java

Respondido el 05 de junio de 20 a las 06:06

Si desea modificar una gran cantidad de clases que no tenían serialVersionUID configurado en primer lugar mientras mantiene la compatibilidad con las clases antiguas, herramientas como IntelliJ Idea, Eclipse se quedan cortas ya que generan números aleatorios y no funcionan en un montón de archivos en una ida. Se me ocurrió el siguiente script bash (lo siento por los usuarios de Windows, considere comprar una Mac o convertirla a Linux) para corregir el problema de serialVersionUID con facilidad:

base_dir=$(pwd)                                                                  
src_dir=$base_dir/src/main/java                                                  
ic_api_cp=$base_dir/target/classes                                               

while read f                                                                     
do                                                                               
    clazz=${f//\//.}                                                             
    clazz=${clazz/%.java/}                                                       
    seruidstr=$(serialver -classpath $ic_api_cp $clazz | cut -d ':' -f 2 | sed -e 's/^\s\+//')
    perl -ni.bak -e "print $_; printf qq{%s\n}, q{    private $seruidstr} if /public class/" $src_dir/$f
done

guarde este script, diga add_serialVersionUID.sh ~ / bin. Luego lo ejecuta en el directorio raíz de su proyecto Maven o Gradle como:

add_serialVersionUID.sh < myJavaToAmend.lst

Este .lst incluye la lista de archivos java para agregar el serialVersionUID en el siguiente formato:

com/abc/ic/api/model/domain/item/BizOrderTransDO.java
com/abc/ic/api/model/domain/item/CardPassFeature.java
com/abc/ic/api/model/domain/item/CategoryFeature.java
com/abc/ic/api/model/domain/item/GoodsFeature.java
com/abc/ic/api/model/domain/item/ItemFeature.java
com/abc/ic/api/model/domain/item/ItemPicUrls.java
com/abc/ic/api/model/domain/item/ItemSkuDO.java
com/abc/ic/api/model/domain/serve/ServeCategoryFeature.java
com/abc/ic/api/model/domain/serve/ServeFeature.java
com/abc/ic/api/model/param/depot/DepotItemDTO.java
com/abc/ic/api/model/param/depot/DepotItemQueryDTO.java
com/abc/ic/api/model/param/depot/InDepotDTO.java
com/abc/ic/api/model/param/depot/OutDepotDTO.java

Este script utiliza la herramienta JDK serialVer bajo el capó. Así que asegúrese de que su $ JAVA_HOME / bin esté en la RUTA.

Respondido el 27 de junio de 15 a las 15:06

Me da una idea: siempre regenere el uid de la versión serial con una herramienta como esta, nunca a mano, antes de hacer un lanzamiento; de esa manera, evita olvidarse de hacer un cambio en una clase cuyo uid de la versión serial debería haber cambiado debido a un cambio incompatible. Hacer un seguimiento de eso manualmente es muy difícil. - Ignazio

Esta pregunta está muy bien documentada en Effective Java de Joshua Bloch. Un libro muy bueno y una lectura obligada. Resumiré algunas de las razones a continuación:

El tiempo de ejecución de la serialización genera un número llamado Versión serial para cada clase serializable. Este número se llama serialVersionUID. Ahora hay algo de matemática detrás de este número y se basa en los campos / métodos que se definen en la clase. Para la misma clase se genera la misma versión cada vez. Este número se utiliza 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 un serialVersionUID diferente al de la clase del remitente correspondiente, la deserialización dará como resultado una InvalidClassException.

Si la clase es serializable, también puede declarar su propio serialVersionUID explícitamente declarando un campo llamado "serialVersionUID" que debe ser estático, final y de tipo long. La mayoría de los IDE como Eclipse te ayudan a generar esa cadena larga.

Respondido 03 ago 15, 22:08

Cada vez que se serializa un objeto, el objeto se marca con un número de identificación de versión para la clase del objeto. serialVersionUID y se calcula basándose en información sobre la estructura de clases. Suponga que creó una clase de Empleado y tiene la ID de versión # 333 (asignada por JVM). Ahora, cuando serialice el objeto de esa clase (Suponga que el objeto Empleado), JVM le asignará el UID como # 333.

Considere una situación: en el futuro, debe editar o cambiar su clase y, en ese caso, cuando la modifique, JVM le asignará un nuevo UID (suponga que # 444). Ahora, cuando intente deserializar el objeto de empleado, JVM comparará el ID de versión (# 333) del objeto serializado (objeto de empleado) con el de la clase, es decir, # 444 (desde que se cambió). En comparación, JVM encontrará que ambas versiones de UID son diferentes y, por lo tanto, la deserialización fallará. Por lo tanto, si el propio programador define serialVersionID para cada clase. Será lo mismo incluso si la clase evoluciona en el futuro y, por lo tanto, JVM siempre encontrará que la clase es compatible con el objeto serializado aunque la clase haya cambiado. Para obtener más información, puede consultar el capítulo 14 de HEAD FIRST JAVA.

contestado el 23 de mayo de 17 a las 15:05

Cada vez que el clase de un objeto se serializa el serialVersionUID es transmitida. No se envía con todos los objetos. - user207421

Una explicación simple:

  1. ¿Estás serializando datos?

    La serialización consiste básicamente en escribir datos de clase en un archivo / flujo / etc. La deserialización consiste en volver a leer esos datos en una clase.

  2. ¿Tiene la intención de entrar en producción?

    Si solo está probando algo con datos falsos o sin importancia, no se preocupe (a menos que esté probando la serialización directamente).

  3. ¿Es esta la primera versión?

    Si es así, establezca serialVersionUID=1L.

  4. ¿Es esta la segunda, tercera, etc. versión de prod?

    Ahora debes preocuparte por serialVersionUID, y debería analizarlo en profundidad.

Básicamente, si no actualiza la versión correctamente cuando actualiza una clase que necesita escribir / leer, obtendrá un error cuando intente leer datos antiguos.

Respondido 12 Abr '19, 16:04

'serialVersionUID' es un número de 64 bits que se utiliza para identificar de forma única una clase durante el proceso de deserialización. Cuando serializas un objeto, serialVersionUID de la clase también se escribe en el archivo. Siempre que deserialice este objeto, el tiempo de ejecución de Java extrae este valor serialVersionUID de los datos serializados y compare el mismo valor asociado con la clase. Si ambos no coinciden, se lanzará 'java.io.InvalidClassException'.

Si una clase serializable no declara explícitamente un serialVersionUID, entonces el tiempo de ejecución de serialización calculará el valor serialVersionUID para esa clase en función de varios aspectos de la clase como campos, métodos, etc. enlace para la aplicación de demostración.

Respondido el 20 de enero de 20 a las 18:01

En resumen, este campo se utiliza para comprobar si los datos serializados se pueden deserializar correctamente. La serialización y deserialización a menudo se realizan mediante diferentes copias del programa; por ejemplo, el servidor convierte el objeto en una cadena y el cliente convierte la cadena recibida en un objeto. Este campo dice que ambos operan con la misma idea sobre qué es este objeto. Este campo ayuda cuando:

  • tiene muchas copias diferentes de su programa en diferentes lugares (como 1 servidor y 100 clientes). Si cambia su objeto, modifica su número de versión y se olvida de actualizar uno de estos clientes, sabrá que no es capaz de deserialización.

  • ha almacenado sus datos en algún archivo y luego intenta abrirlo con la versión actualizada de su programa con el objeto modificado; sabrá que este archivo no es compatible si mantiene su versión correcta

Cuando es importante

Lo más obvio: si agrega algunos campos a su objeto, las versiones anteriores no podrán usarlos porque no tienen estos campos en su estructura de objeto.

Menos obvio: cuando deserializa un objeto, los campos que no están presentes en la cadena se mantendrán como NULL. Si ha eliminado el campo de su objeto, las versiones anteriores mantendrán este campo como siempre NULL, lo que puede provocar un mal comportamiento si las versiones anteriores dependen de los datos de este campo (de todos modos, lo ha creado para algo, no solo por diversión :-))

Menos obvio: a veces cambia la idea que pone en el significado de algún campo. Por ejemplo, cuando tienes 12 años te refieres a "bicicleta" debajo de "bicicleta", pero cuando tienes 18 te refieres a "motocicleta", si tus amigos te invitan a "andar en bicicleta por la ciudad" y serás el único que vino en bicicleta, comprenderá lo importante que es mantener el mismo significado en todos los campos :-)

Respondido 15 Abr '19, 19:04

En primer lugar, para responder a su pregunta, cuando no declaramos SerialVersionUID en nuestra clase, el tiempo de ejecución de Java lo genera para nosotros, pero ese proceso es sensible a muchos metadatos de la clase, incluido el número de campos, el tipo de campos, el modificador de acceso de los campos, la interfaz implementada por clase, etc. Por lo tanto, se recomienda declararlo nosotros mismos y Eclipse le advierte sobre lo mismo.

Serialización: A menudo trabajamos con objetos importantes cuyo estado (datos en las variables del objeto) es tan importante que no podemos arriesgarnos a perderlo por fallas de energía / sistema (o) fallas de red en caso de enviar el estado del objeto a otros máquina. La solución para este problema se llama "Persistencia", que simplemente significa conservar (mantener / guardar) los datos. La serialización es una de las muchas otras formas de lograr la persistencia (guardando datos en el disco / memoria). Al guardar el estado del objeto, es importante crear una identidad para el objeto, para poder leerlo correctamente (deserialización). Esta identificación única es ID es SerialVersionUID.

Respondido 29 Abr '19, 08:04

¿Qué es SerialVersionUID? Respuesta: - Digamos que hay dos personas, una de HQ y otra de ODC, ambas van a realizar la serialización y deserialización respectivamente. En este caso, para autenticar que el receptor que está en ODC es la persona autenticada, JVM crea una ID única que se conoce como SerialVersionUID.

Aquí hay una buena explicación basada en el escenario,

¿Por qué SerialVersionUID?

Publicación por entregas : En el momento de la serialización, con cada objeto del lado del remitente, la JVM guardará un Identificador único. JVM es responsable de generar ese ID único basado en el archivo .class correspondiente que está presente en el sistema del remitente.

Deserialización: En el momento de la deserialización, la JVM del lado del receptor comparará la ID única asociada con el Objeto con la ID única de la clase local, es decir, la JVM también creará una ID única basada en el archivo .class correspondiente que está presente en el sistema del receptor. Si ambos ID únicos coinciden, solo se realizará la deserialización. De lo contrario, obtendremos Runtime Exception que dice InvalidClassException. Este identificador único no es más que SerialVersionUID

respondido 15 nov., 19:19

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.