Serialização de objetos em Java: guia completo com exemplos

Treinador Online de Python para Iniciantes

Aprenda Python facilmente sem sobrecarga teórica. Resolva tarefas práticas com verificação automática e escreva código diretamente no navegador.

Start Course

Serialização de objetos em Java: do básico às técnicas avançadas



Serialização é o processo de converter o estado de um objeto em um fluxo de bytes para salvá-lo (em arquivo, banco de dados) ou transmiti-lo pela rede. O processo inverso — desserialização — restaura o objeto a partir do fluxo de bytes. Em Java, esse mecanismo é integrado à plataforma e amplamente utilizado em sistemas distribuídos, cache e aplicações web. Neste artigo, vamos explorar como a serialização funciona, quais interfaces e classes estão envolvidas e como implementar corretamente a serialização personalizada.



Fundamentos: a interface Serializable



Para que um objeto possa ser serializado, sua classe deve implementar a interface marcadora java.io.Serializable. Essa interface não contém métodos — ela apenas informa à máquina virtual que o objeto pode ser serializado.



import java.io.Serializable;

public class User implements Serializable { private static final long serialVersionUID = 1L; private String name; private int age;

public User(String name, int age) { this.name = name; this.age = age; }

@Override public String toString() { return "User{name='" + name + "', age=" + age + "}"; }}


O campo serialVersionUID é um identificador único da versão da classe. Se não for declarado explicitamente, a JVM o calculará automaticamente, mas isso pode causar InvalidClassException durante a desserialização se a classe for alterada. Recomenda-se sempre defini-lo manualmente.



Processo de serialização e desserialização



Para gravar um objeto em um fluxo, usa-se ObjectOutputStream; para ler, ObjectInputStream. Vejamos um exemplo básico:



import java.io.*;

public class SerializationDemo { public static void main(String[] args) { User user = new User("Alexei", 30);

// Serialização try (FileOutputStream fos = new FileOutputStream("user.ser"); ObjectOutputStream oos = new ObjectOutputStream(fos)) { oos.writeObject(user); System.out.println("Objeto serializado: " + user); } catch (IOException e) { e.printStackTrace(); }

// Desserialização try (FileInputStream fis = new FileInputStream("user.ser"); ObjectInputStream ois = new ObjectInputStream(fis)) { User restoredUser = (User) ois.readObject(); System.out.println("Objeto restaurado: " + restoredUser); } catch (IOException | ClassNotFoundException e) { e.printStackTrace(); } }}


Na desserialização, o construtor do objeto não é chamado — o estado é restaurado diretamente do fluxo. Essa é uma diferença importante em relação à criação normal de objetos com new.



A palavra-chave transient



Às vezes, é necessário excluir alguns campos da serialização, como senhas ou cálculos temporários. Para isso, usa-se o modificador transient. Campos marcados com ele recebem valores padrão (0, null, false) durante a serialização.



public class UserWithPassword implements Serializable {    private static final long serialVersionUID = 1L;    private String login;    private transient String password; // não será serializado

public UserWithPassword(String login, String password) { this.login = login; this.password = password; }

@Override public String toString() { return "User{login='" + login + "', password='" + password + "'}"; }}


Após a desserialização, o campo password será null. Isso é útil para segurança, mas requer lógica adicional de restauração.



Serialização personalizada: métodos writeObject e readObject



Se o comportamento padrão não for adequado, é possível sobrescrever os métodos privados

Recommendations