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.