Java - Serialização
Java fornece um mecanismo, chamado serialização de objeto, onde um objeto pode ser representado como uma sequência de bytes que inclui os dados do objeto, bem como informações sobre o tipo do objeto e os tipos de dados armazenados no objeto.
Depois que um objeto serializado é gravado em um arquivo, ele pode ser lido do arquivo e desserializado, ou seja, as informações de tipo e bytes que representam o objeto e seus dados podem ser usados para recriar o objeto na memória.
O mais impressionante é que todo o processo é independente da JVM, o que significa que um objeto pode ser serializado em uma plataforma e desserializado em uma plataforma totalmente diferente.
Aulas ObjectInputStream e ObjectOutputStream são fluxos de alto nível que contêm os métodos para serializar e desserializar um objeto.
A classe ObjectOutputStream contém muitos métodos de gravação para escrever vários tipos de dados, mas um método em particular se destaca -
public final void writeObject(Object x) throws IOException
O método acima serializa um objeto e o envia para o fluxo de saída. Da mesma forma, a classe ObjectInputStream contém o seguinte método para desserializar um objeto -
public final Object readObject() throws IOException, ClassNotFoundException
Este método recupera o próximo Object fora do stream e o desserializa. O valor de retorno é Object, portanto, você precisará convertê-lo em seu tipo de dados apropriado.
Para demonstrar como a serialização funciona em Java, vou usar a classe Employee que discutimos no início do livro. Suponha que tenhamos a seguinte classe Employee, que implementa a interface Serializable -
Exemplo
public class Employee implements java.io.Serializable {
public String name;
public String address;
public transient int SSN;
public int number;
public void mailCheck() {
System.out.println("Mailing a check to " + name + " " + address);
}
}
Observe que para uma classe ser serializada com sucesso, duas condições devem ser atendidas -
A classe deve implementar a interface java.io.Serializable.
Todos os campos da classe devem ser serializáveis. Se um campo não for serializável, ele deve ser marcadotransient.
Se você está curioso para saber se uma classe padrão Java é serializável ou não, verifique a documentação da classe. O teste é simples: se a classe implementa java.io.Serializable, ela é serializável; caso contrário, não é.
Serializando um objeto
A classe ObjectOutputStream é usada para serializar um Object. O programa SerializeDemo a seguir instancia um objeto Employee e o serializa em um arquivo.
Quando a execução do programa termina, um arquivo chamado employee.ser é criado. O programa não gera nenhuma saída, mas estuda o código e tenta determinar o que o programa está fazendo.
Note - Ao serializar um objeto para um arquivo, a convenção padrão em Java é dar ao arquivo um .ser extensão.
Exemplo
import java.io.*;
public class SerializeDemo {
public static void main(String [] args) {
Employee e = new Employee();
e.name = "Reyan Ali";
e.address = "Phokka Kuan, Ambehta Peer";
e.SSN = 11122333;
e.number = 101;
try {
FileOutputStream fileOut =
new FileOutputStream("/tmp/employee.ser");
ObjectOutputStream out = new ObjectOutputStream(fileOut);
out.writeObject(e);
out.close();
fileOut.close();
System.out.printf("Serialized data is saved in /tmp/employee.ser");
} catch (IOException i) {
i.printStackTrace();
}
}
}
Desserializando um objeto
O programa DeserializeDemo a seguir desserializa o objeto Employee criado no programa SerializeDemo. Estude o programa e tente determinar seu resultado -
Exemplo
import java.io.*;
public class DeserializeDemo {
public static void main(String [] args) {
Employee e = null;
try {
FileInputStream fileIn = new FileInputStream("/tmp/employee.ser");
ObjectInputStream in = new ObjectInputStream(fileIn);
e = (Employee) in.readObject();
in.close();
fileIn.close();
} catch (IOException i) {
i.printStackTrace();
return;
} catch (ClassNotFoundException c) {
System.out.println("Employee class not found");
c.printStackTrace();
return;
}
System.out.println("Deserialized Employee...");
System.out.println("Name: " + e.name);
System.out.println("Address: " + e.address);
System.out.println("SSN: " + e.SSN);
System.out.println("Number: " + e.number);
}
}
Isso produzirá o seguinte resultado -
Resultado
Deserialized Employee...
Name: Reyan Ali
Address:Phokka Kuan, Ambehta Peer
SSN: 0
Number:101
Aqui estão os seguintes pontos importantes a serem observados -
O bloco try / catch tenta capturar uma ClassNotFoundException, que é declarada pelo método readObject (). Para que uma JVM seja capaz de desserializar um objeto, ela deve ser capaz de encontrar o bytecode para a classe. Se a JVM não puder encontrar uma classe durante a desserialização de um objeto, ela lançará uma ClassNotFoundException.
Observe que o valor de retorno de readObject () é convertido em uma referência de Employee.
O valor do campo SSN era 11122333 quando o objeto foi serializado, mas como o campo é temporário, esse valor não foi enviado para o fluxo de saída. O campo SSN do objeto Employee desserializado é 0.