O processo de serialização de objetos permite converter a representação de um objeto em memória para uma seqüência de bytes que pode então ser enviada para um ObjectOutputStream, que por sua vez pode estar associado a um arquivo em disco ou a uma conexão de rede, por exemplo.
Por exemplo, para serializar um objeto da classe
java.util.Hashtable
, armazenando seu contéudo em um
arquivo em disco, a seqüência de passos é:
// criar/manipular o objeto Hashtable dados = new Hashtable(); ... // definir o nome do arquivo String filename = ...; // abrir o arquivo de saída File file = new File(filename); if(!file.exists()){ file.createNewFile(); } FileOutputStream out = new FileOutputStream(file); // associar ao arquivo o ObjectOutputStream ObjectOutputStream s = new ObjectOutputStream(out); // serializar o objeto s.writeObject(dados);
O processo inverso, a desserialização, permite ler essa representação
de um objeto a partir de um ObjectInputStream usando o método
readObject()
:
FileInputStream in = new FileInputStream(file); ObjectInputStream s = new ObjectInputStream(in); dados = (Hashtable) s.readObject();
Objetos de classes para os quais são previstas serializações e desserializações devem implementar a interface java.io.Serializable, que não define nenhum método ou campo -- é uma interface marker, servindo apenas para registrar a semântica de serialização.
A serialização de um objeto deve ser implementada pela definição de um método writeObject(), com assinatura:
private void writeObject(java.io.ObjectOutputStream out) throws IOException
Tipicamente, esse método realiza qualquer preparação necessária para a serialização e invoca o método defaultWriteObject() da classe ObjectOutputStream.
A desserialização é implementada pelo método readObject() com assinatura:
private void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException;
Esse método tipicamente invoca defaultReadObject() da classe ObjectInputStream e então realiza as ações complementares àquelas realizadas em writeObject(), tais como leitura de dados adicionais e inicialização de variáveis.
Serialização é um processo transitivo, ou seja, subclasses serializáveis de classes serializáveis são automaticamente incorporadas à representação serializada do objeto raiz. Para que o processo de desserialização possa operar corretamente, todas as classes envolvidas no processo devem ter um construtor default (sem argumentos).
Caso deseje-se controle total sobre o processe de serialização e desserialização de objetos (ao invés de usar os métodos defaultWriteObject() e defaultReadObject()), a interface java.io.Externalizable (uma extensão de Serializable) deve ser utilizada. Essa interface define os métodos:
writeExternal
public abstract void writeExternal(ObjectOutput out) throws IOException
|
readExternal
public abstract void readExternal(ObjectInput in) throws IOException, ClassNotFoundException
|
© Ivan Luiz Marques Ricarte
DCA/FEEC/UNICAMP