una tipos serializar serializacion libreria guardar deserializacion como clase java serialization

tipos - Serialización Java con partes no serializables



serializacion y deserializacion en java (10)

Como señaló otra persona, el capítulo 11 de Effective Java de Josh Bloch es un recurso indispensable en Serialización Java.

Un par de puntos de ese capítulo relacionados con su pregunta:

  • suponiendo que desea serializar el estado del campo no serializable en MyClass2, ese campo debe ser accesible para MyClass, ya sea directamente o a través de getters y setters. MyClass tendrá que implementar una serialización personalizada al proporcionar los métodos readObject y writeObject.
  • la Clase del campo no serializable debe tener una API que permita obtener su estado (para escribir en la secuencia del objeto) y luego instanciar una nueva instancia con ese estado (cuando más tarde lea la secuencia del objeto).
  • según el ítem 74 de Java efectivo, MyClass2 debe tener un constructor sin argumentos accesible para MyClass; de lo contrario, es imposible que MyClass extienda MyClass2 e implemente Serializable.

He escrito un ejemplo rápido a continuación que ilustra esto.

class MyClass extends MyClass2 implements Serializable{ public MyClass(int quantity) { setNonSerializableProperty(new NonSerializableClass(quantity)); } private void writeObject(java.io.ObjectOutputStream out) throws IOException{ // note, here we don''t need out.defaultWriteObject(); because // MyClass has no other state to serialize out.writeInt(super.getNonSerializableProperty().getQuantity()); } private void readObject(java.io.ObjectInputStream in) throws IOException { // note, here we don''t need in.defaultReadObject(); // because MyClass has no other state to deserialize super.setNonSerializableProperty(new NonSerializableClass(in.readInt())); } } /* this class must have no-arg constructor accessible to MyClass */ class MyClass2 { /* this property must be gettable/settable by MyClass. It cannot be final, therefore. */ private NonSerializableClass nonSerializableProperty; public void setNonSerializableProperty(NonSerializableClass nonSerializableProperty) { this.nonSerializableProperty = nonSerializableProperty; } public NonSerializableClass getNonSerializableProperty() { return nonSerializableProperty; } } class NonSerializableClass{ private final int quantity; public NonSerializableClass(int quantity){ this.quantity = quantity; } public int getQuantity() { return quantity; } }

Yo tengo:

class MyClass extends MyClass2 implements Serializable { //... }

En MyClass2 es una propiedad que no es serializable. ¿Cómo puedo serializar (y deserializar) este objeto?

Corrección: MyClass2 es, por supuesto, no una interfaz sino una clase.


Depende de por qué ese miembro de MyClass2 no es serializable.

Si hay alguna buena razón por la cual MyClass2 no se puede representar en forma serializada, entonces es probable que la misma razón se aplique a MyClass, ya que es una subclase.

Es posible escribir un formulario serializado personalizado para MyClass implementando readObject y writeObject, de tal manera que el estado de los datos de la instancia de MyClass2 en MyClass pueda recrearse adecuadamente a partir de los datos serializados. Este sería el camino a seguir si la API de MyClass2 está arreglada y no puede agregar Serializable.

Pero primero debes averiguar por qué MyClass2 no es serializable, y tal vez cambiarlo.


MyClass2 es solo una interfaz, así que técnicamente no tiene propiedades, solo métodos. Dicho esto, si tiene variables de instancia que no son serializables, la única forma que conozco de evitarlo es declarar esos campos transitorios.

ex:

private transient Foo foo;

Cuando declara un campo transitorio, se ignorará durante el proceso de serialización y deserialización. Tenga en cuenta que cuando deserializa un objeto con un campo transitorio, el valor de ese campo siempre será el predeterminado (generalmente nulo).

Tenga en cuenta que también puede anular el método readResolve () de su clase para inicializar campos transitorios basados ​​en otro estado del sistema.


Puede comenzar mirando la palabra clave transitoria , que marca los campos como no parte del estado persistente de un objeto.


Si es posible, las partes no serializables se pueden establecer como transitorias

private transient SomeClass myClz;

De lo contrario, puedes usar Kryo . Kryo es un marco de serialización de gráficos de objetos rápido y eficiente para Java (por ejemplo, la serialización JAVA de java.awt.Color requiere 170 bytes, Kryo solo 4 bytes), que puede serializar también objetos no serializables. Kryo también puede realizar copias / clonaciones profundas y superficiales automáticas. Esto es copia directa de objeto a objeto, no object->bytes->object .

Aquí hay un ejemplo de cómo usar kryo

Kryo kryo = new Kryo(); // #### Store to disk... Output output = new Output(new FileOutputStream("file.bin")); SomeClass someObject = ... kryo.writeObject(output, someObject); output.close(); // ### Restore from disk... Input input = new Input(new FileInputStream("file.bin")); SomeClass someObject = kryo.readObject(input, SomeClass.class); input.close();

Los objetos serializados también se pueden comprimir registrando el serializador exacto:

kryo.register(SomeObject.class, new DeflateCompressor(new FieldSerializer(kryo, SomeObject.class)));


Si puede modificar MyClass2, la forma más fácil de solucionar esto es declarar la propiedad transitoria.


Tendrá que implementar writeObject() y readObject() y realizar la serialización / deserialización manual de esos campos. Consulte la página de javadoc para java.io.Serializable para más detalles. Effective Java de Josh Bloch también tiene algunos buenos capítulos sobre la implementación de una serialización robusta y segura.


Un método útil para serializar instancias de clases no serializables (o al menos subclases de) se conoce como un Serial Proxy. Esencialmente implementamos writeReplace para devolver una instancia de una clase serializable completamente diferente que implementa readResolve para devolver una copia del objeto original. Escribí un ejemplo de serialización java.awt.BasicStroke en Usenet


Varias posibilidades surgieron y las reanudo aquí:

  • Implementar writeObject () y readObject () como sugirió
  • Declarar la propiedad transitoria y no se serializará como se indica por primera vez en
  • use XStream como lo establece boris-terzic
  • use un Proxy serial como lo establece tom-hawtin-tackline

XStream es una gran biblioteca para hacer una serialización rápida de Java a XML para cualquier objeto, sin importar si es Serializable o no. Incluso si el formato de destino XML no le conviene, puede usar el código fuente para aprender cómo hacerlo.