¿Cómo serializar los miembros de datos estáticos de una clase de Java?

Cuando serializamos objetos, los miembros estáticos no se serializan, pero si tenemos que hacerlo, ¿hay alguna salida?

La primera pregunta es por qué necesita serializar los miembros estáticos?

Los miembros estáticos están asociados con la clase, no con las instancias, por lo que no tiene sentido incluirlos al serializar una instancia.

La primera solución es hacer que esos miembros no sean estáticos. O bien, si esos miembros son los mismos en la clase original y la clase objective (misma clase, pero posiblemente en entornos de tiempo de ejecución diferentes), no los serialice en absoluto.

Tengo algunas ideas sobre cómo se puede enviar a través de miembros estáticos, pero primero necesito ver el caso de uso, ya que en todos los casos eso significa actualizar la clase objective, y no he encontrado una buena razón para hacerlo.

Amigos, estático no significa INMUTABLE. Por ejemplo, es posible que desee serializar todo el estado del cálculo (sí, incluidos los campos estáticos, contadores, etc.) para reanudarlo más tarde, después de reiniciar JVM y / o la computadora host.

La respuesta correcta a eso, como ya se dijo, es usar interfaz Externalizable, no Serializable. Entonces tienes un control completo sobre qué y cómo externalizas.

Puede controlar la serialización implementando:

private void writeObject(ObjectOutputStream out) throws IOException; private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException; 

Hay una descripción completa de la serialización http://java.sun.com/developer/technicalArticles/Programming/serialization/ .

Como han dicho otras respuestas, realmente no tiene sentido serializar estática ya que es el objeto, no la clase que está serializando y necesita hacer, huele como si tuviera otros problemas con su código para mí.

Esta es la serialización para el campo estático: newBookingNumber.

 class Booking implements Serializable { /** * Generated serial version ID. */ private static final long serialVersionUID = 5316748056989930874L; // To hold new booking number. private static int newBookingNumber = 0; // The booking number. private int bookingNumber; /* * Default serializable fields of a class are defined to be * the non-transient and non-static fields. So, we have to * write and read the static field separately. */ private void writeObject(ObjectOutputStream oos) throws IOException { oos.defaultWriteObject(); oos.writeObject(new Integer(newBookingNumber)); } private void readObject(ObjectInputStream ois) throws ClassNotFoundException, IOException { ois.defaultReadObject(); newBookingNumber = (Integer)ois.readObject(); } } 

Buenas respuestas y comentarios: no lo hagas. ¿Pero cómo?

Lo más probable es que lo mejor sea crear un objeto para contener todas sus “Estáticas”. Ese objeto probablemente también tenga métodos estáticos de tu clase.

Cada instancia de su clase puede contener esta otra clase, o si realmente tiene que hacerlo, puede convertirlo en un singleton al que cualquier miembro puede acceder.

Después de hacer este refactorizador, descubrirá que debería haberlo hecho así todo el tiempo. Incluso puede descubrir que algunas de sus limitaciones de diseño previas que lo estaban molestando en un nivel de subconcesamiento se han desvanecido.

Probablemente descubrirá que esta solución también resuelve otros problemas de serialización que aún no había notado.

Puede hacerlo sin tener que actualizar manualmente su clase cada vez que simplemente cambie un campo. Es posible que desee hacer esto si desea tener la facilidad de los miembros estáticos para acceder a la configuración en una aplicación, pero también desea guardar esa configuración. En este caso, también desearía tener la opción de aplicarlos a su antojo, no cargarlos de manera predeterminada ya que las otras soluciones aquí lo requieren, ya que son estáticos. Esto permite la reversión de configuraciones por razones obvias.

Básicamente, utilice los métodos de campo para obtener todos los miembros de la clase, luego asigne los nombres completos de estos campos a los contenidos. El nombre completo es obligatorio ya que Field no es serializable. Serialice esta asignación y vuelva a instalarla para obtener la configuración guardada.

La segunda parte del rompecabezas es el tipo de función apply (). Esto pasa por la asignación y aplica lo que puede a la clase estática.

También debe asegurarse de que los contenidos de los miembros estáticos sean ellos mismos serializables.

Como se puede ver con suerte en esta clase de ejemplo, los miembros estáticos se pueden guardar y devolver fácilmente. Dejaré que el implementador se preocupe por los UID de las clases, las salvaguardas, etc. isSameAs () se usa para las pruebas unitarias. AppSettings es la clase que contiene todos los campos estáticos que desea serializar.

 public class AppSettingsReflectorSaver implements Serializable { HashMap genericNamesAndContents = new HashMap(); private AppSettingsReflectorSaver() { } static AppSettingsReflectorSaver createAppSettingsSaver() { AppSettingsReflectorSaver ret = new AppSettingsReflectorSaver(); ret.copyAppSettings(); return ret; } private void copyAppSettings() { Field[] fields = AppSettings.class.getFields(); for (Field field : fields) { mapContentsForSerialization(field); } } private void mapContentsForSerialization(Field field) { try { Object fieldContents = field.get(AppSettings.class); genericNamesAndContents.put(field.toGenericString(), fieldContents); } catch (IllegalArgumentException ex) { Logger.getLogger(AppSettingsReflectorSaver.class.getName()).log(Level.SEVERE, null, ex); } catch (IllegalAccessException ex) { Logger.getLogger(AppSettingsReflectorSaver.class.getName()).log(Level.SEVERE, null, ex); } } boolean isSameAs(AppSettingsReflectorSaver now) { for( String thisKey : genericNamesAndContents.keySet()){ boolean otherHasThisKey = now.genericNamesAndContents.containsKey(thisKey); Object thisObject = genericNamesAndContents.get(thisKey); Object otherObject = now.genericNamesAndContents.get(thisKey); boolean otherHasThisValue = thisObject.equals(otherObject); if (!otherHasThisKey || !otherHasThisValue){ return false; } } return true; } void applySavedSettingsToStatic() { Field[] fields = AppSettings.class.getFields(); for (Field field : fields) { if (!genericNamesAndContents.containsKey(field.toGenericString())){ continue; } Object content = genericNamesAndContents.get(field.toGenericString() ); try { field.set(AppSettings.class, content); } catch (IllegalArgumentException ex) { Logger.getLogger(AppSettingsReflectorSaver.class.getName()).log(Level.SEVERE, null, ex); } catch (IllegalAccessException ex) { Logger.getLogger(AppSettingsReflectorSaver.class.getName()).log(Level.SEVERE, null, ex); } } } 

}

Esta es mi primera publicación, ve bien conmigo: P ~

Los miembros estáticos pertenecen a la clase, no a los objetos individuales.

Debes reconsiderar tu estructura de datos.

Para tener una implementación compacta, implemente readObject y writeObject en su clase, llame a los métodos defaultReadObject y defaultWriteObject dentro de los métodos que manejan la serialización normal y luego continúe con la serialización y deserialización de los campos adicionales que necesite.

Saludos, GK

Sí, podemos serializar las variables estáticas. Pero podemos escribir nuestro propio writeObject() y readObject() . Creo que esto puede resolver el problema.