Atualizado: 21/09/2025

Este conteúdo é original e não foi gerado por inteligência artificial.

Serialização de Objetos com ObjectOutputStream e ObjectInputStream

Serialização é o processo de converter o estado de um objeto em uma sequência de bytes. Essa abordagem é fundamental para persistir o estado de um objeto em disco, transferi-lo pela rede ou para mecanismos de cache. O processo inverso, que reconstrói o objeto a partir dos bytes, é a desserialização.

A Interface Serializable

Para que um objeto possa ser serializado, sua classe deve implementar a interface java.io.Serializable. Esta é uma interface de marcação, o que significa que ela não possui métodos. Sua única finalidade é sinalizar para a JVM que os objetos daquela classe podem ser serializados.

Serialização com ObjectOutputStream

A classe ObjectOutputStream "envolve" um OutputStream e adiciona a capacidade de escrever objetos inteiros. Ela herda toda a funcionalidade de DataOutputStream para escrever tipos primitivos e adiciona o método crucial para serializar objetos:

  • void writeObject(Object obj): serializa o objeto e o grava no stream.
  • void writeBoolean(boolean val): grava um valor booleano.
  • void writeByte(int val): grava um byte.
  • void writeChar(int val): grava um char.
  • void writeDouble(double val): grava um double.
  • void writeFloat(float val): grava um float.
  • void writeInt(int val): grava um int.
  • void writeLong(long val): grava um long.
  • void writeShort(int val): grava um short.
  • void writeUTF(String str): grava uma string em formato UTF-8 modificado.
  • void write(byte[] buf): grava um array de bytes.
  • void flush(): força a escrita dos dados em buffer para o stream.
  • void close(): fecha o stream.

Desserialização com ObjectInputStream

A classe ObjectInputStream realiza o processo inverso. Ela herda a funcionalidade de DataInputStream para ler tipos primitivos e adiciona o método para desserializar objetos:

  • Object readObject(): lê e desserializa um objeto do stream.
  • boolean readBoolean()
  • byte readByte()
  • char readChar()
  • double readDouble()
  • float readFloat()
  • int readInt()
  • long readLong()
  • short readShort()
  • String readUTF()
  • int available(): retorna o número de bytes disponíveis para leitura.
  • void close(): fecha o stream.

Exemplo Prático de Serialização e Desserialização

import java.io.*;

public class Program {

    public static void main(String[] args) {

        // Serialização
        try (ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("person.dat"))) {
            Person p = new Person("Sam", 33, 178.5, true);
            oos.writeObject(p);
            System.out.println("Object has been serialized");
        } catch (Exception ex) {
            System.out.println(ex.getMessage());
        }

        // Desserialização
        try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream("person.dat"))) {
            Person p = (Person) ois.readObject();
            System.out.printf("Name: %s \t Age: %d \n", p.getName(), p.getAge());
        } catch (Exception ex) {
            System.out.println(ex.getMessage());
        }
    }
}

class Person implements Serializable {
    private static final long serialVersionUID = 1L;

    private String name;
    private int age;
    private double height;
    private boolean married;

    Person(String n, int a, double h, boolean m) {
        this.name = n;
        this.age = a;
        this.height = h;
        this.married = m;
    }

    String getName() { return name; }
    int getAge() { return age; }
    double getHeight() { return height; }
    boolean isMarried() { return married; }
}

Considerações Importantes

Versionamento com serialVersionUID

Para controlar a compatibilidade entre diferentes versões de uma classe, é uma prática essencial declarar explicitamente um campo serialVersionUID:

private static final long serialVersionUID = 1L;

Este ID é usado durante a desserialização para verificar se a classe do objeto serializado é compatível com a classe disponível na JVM.

Excluindo Dados com transient

Para impedir que certos campos sejam serializados (como senhas ou dados temporários), marque-os com a palavra-chave transient.

class User implements Serializable {
    private static final long serialVersionUID = 1L;

    private String username;
    private transient String password; // Não será serializado

    public User(String username, String password) {
        this.username = username;
        this.password = password;
    }

    public String getUsername() {
        return username;
    }

    public String getPassword() {
        return password; // Retornará null após a desserialização
    }

    @Override
    public String toString() {
        return "User{" +
               "username='" + username + '\'' +
               ", password='" + (password == null ? "TRANSIENT" : "******") + '\'' +
               '}';
    }
}

Na desserialização, o campo password receberá seu valor padrão (null).

Riscos de Segurança

Nunca desserialize dados de uma fonte não confiável. Um invasor pode criar uma sequência de bytes maliciosa que, ao ser desserializada, pode levar à execução de código arbitrário na sua aplicação.


Resumo

  • Serialização converte um objeto em bytes; Desserialização o reconstrói.
  • Uma classe deve implementar Serializable para ser serializável.
  • ObjectOutputStream.writeObject() serializa, e ObjectInputStream.readObject() desserializa.
  • É uma prática essencial declarar um private static final long serialVersionUID para controlar o versionamento.
  • Use transient para excluir campos da serialização.
  • Seja extremamente cauteloso com a desserialização de dados de fontes não confiáveis.
Política de Privacidade

Copyright © www.programicio.com Todos os direitos reservados

É proibida a reprodução do conteúdo desta página sem autorização prévia do autor.

Contato: programicio@gmail.com