Zona HTML Zona Java Zona PHP Zona ASP Zona Bases de datos
-Tutoriales

I/O: Leer y Escibir


Proporcionar Serialización de Objetos para Nuestras Clases

Un objeto es serializable sólo si su clase implementa el interface Serializable. Así, si queremos serializar un ejemplar de una de nuestras clases, la clase debe implementar este interface.

Las buenas noticias es que Serializable es un interface vacío. Es decir, no contiene ninguna declaración de método; su propósito es simplemente identificar las clases cuyos objetos son serializables.

. Implementar el Interface Serializable

Aquí tenemos la definición completa del interface Serializable:

package java.io;
public interface Serializable {
    // there's nothing in here!
};

Crear ejemplares de una clase serializable es fácil. Sólo hay que añadir la claúsula implements Serializable a la declaración de nuestra clase:

public class MySerializableClass implements Serializable {
    ...
}

No tenemos que escribir ningún método. La serialización de un ejemplar de esta clase la maneja el método defaultWriteObject de ObjectOutputStream.

Este método escribe cualquier cosa necesaria para reconstruir un ejemplar de la clase, incluyendo lo siguiente:

  • La clase del Objeto
  • La firma de la clase
  • Los valores para todos los miembros no-transient y no-static, incluyendo los miembros que se refieren a otros objetos.

Para muchas clases, este comportamiento por defecto es suficiente. Sin embargo, la serialización por defecto puede ser lenta, y las clases podrían querer un control más explicito sobre la serialización.

. Personalizar la Serialización

Podemos personalizar la serialización de nuestras clases proporcionando dos métodos para ella: writeObject y readObject.

El método writeObject controla la información que se graba. Normalmente se usa para añadir información adicional al stream. El método readObject lee la información escrita por el correspondiente método writeObject o puede usarse para actualizar el estado del objeto después de haber sido restaurado.

El método writeObject debe declarse exactamente como se muestra en el siguiente ejemplo. Lo primero que debe hacer es llamar al método defaultWriteObject para realizar la serialización por defecto. Cualquier ajuste puede realizarse después.

private void writeObject(ObjectOutputStream s)
                         throws IOException {
    s.defaultWriteObject();
    // customized serialization code
}

El método readObject debe leer todo lo escrito por writeObject en el mismo orden en que se escribió. El método readObject también puede realizar cálculos o actualizar el estado del objeto de alguna forma. Aquí está el método readObject que corresponde al método writeObject anterior:

private void readObject(ObjectInputStream s)
                        throws IOException  {
    s.defaultReadObject();
    // customized deserialization code
    ...
    // followed by code to update the object, if necessary
}

El método readObject debe declarse exactamente como se ha mostrado.

Los métodos writeObject y readObject son responsalbes de serializar sólo las clases inmediatas. Cualquier serialización requerida por la superclase se maneja automáticamente. Sin embargo, una clase que necesita coordinarse explícitamente con su superclase para serializarse puede hacerlo implementando el interface Externalizable.

. Implementar el Interface Externalizable

Para un completo control explícito del proceso de serialización, una clase debe implementar el interface Externalizable. Para los objetos Externalizable sólo la identidad de la clase del objeto es grabada automáticamente en el stream. La clase es responsable de escribir y leer sus contenidos, y debe estar coordinada con su superclase para hacerlo.

Aquí tenemos una definición completa del interface Externalizable que desciende del interface Serializable:

package java.io;
public interface Externalizable extends Serializable
{
    public void writeExternal(ObjectOutput out)
                              throws IOException;
    public void readExternal(ObjectInput in)
                             throws IOException, 
                             java.lang.ClassNotFoundException;
}

Lo siguiente sirve para una clase Externalizable:

  • Debe implementar el interface java.io.Externalizable.
  • Debe implementar un método writeExternal para salvar el estado del objeto. También, debe coordinarse explícitamente con sus superclase para salvar su estado.
  • Debe implementar el método readExternal para leer los datos escritos por el método writeExternal desde el stream y restaurar el estado del objeto. Debe coordinarse explíctamente con su superclase para restaurar sus estado.
  • Si se están escribiendo formatos definidos externamente, los métodos writeExternal y readExternal son los únicos responsables de esos formatos.

Los métodos writeExternal y readExternal son públicos y corren el riesgo de que un cliente pueda escribir o leer información en el objeto distinto usando sus métodos y campos. Estos métodos deben se usarse solamente cuando la información contenida en el objeto no sea importante o cuando exponer dicha información no represente un riesgo de seguridad.

. Proteger la Información Sensible

Cuando desarrollamos una clase que proporcione acceso controlado a recursos, debemos tener cidado de proteger la información y las funciones sensibles. Durante la des-serialización, se restaura el estado privado del objeto. Por ejemplo, un descriptor de fichero contiene un manejador que propociona acceso a un recurso del sistema operativo. Siendo posible olvidar que un descriptor de fichero puede permitir ciertas formas de accesos ilegales, ya que la restauración del estado se hace desde un stream. Por lo tanto en el momento de la serialización se debe tener cuidado y no creer que el stream contiene sólo representaciones válidas de objetos. Para evitar comprometer una clase, debemos evitar que el estado sensible de un objeto sea restaurado desde un stream o que sea reverificado por la clase.

Hay disponibles varias técnicas para proteger los datos sensibles. La más sencilla es marcar los campos que contienen los datos sensibles como private transient.

Los campos transient y static no son serializados. Marcando el campo evitaremos que el estado aparezca en el stream y sea restaurado durante la des-serialización. Como la lectura y escritura (de campos privados) no puede hacerde desde fuera de la clase, los campos transient de la clase son seguros.

Las clases particularmente sensibles no debe ser serializadas. Para conseguir esto, el objeto no debe implementar ninguno de los interfaces Serializable ni Externalizable.

Algunas clases podrían encontrar beneficioso permitir la escritura y lectura pero específicamente manejadas y revalidar el estado cuando es des-serializado. La clase debería implementar los métodos writeObject y readObject para salvar y recuperar sólo el estado apropiado. Si el acceso debe ser denegado, lanzar una NotSerializableException evitará accesos posteriores.

 
Patrocinados
 

Copyright © 1999-2006 Programación en castellano. Todos los derechos reservados.
Formulario de Contacto - Datos legales - Publicidad

Hospedaje web y servidores dedicados linux por Ferca Network