CodeGym /Cursos /JAVA 25 SELF /Análise dos erros mais comuns na serialização de coleções...

Análise dos erros mais comuns na serialização de coleções

JAVA 25 SELF
Nível 44 , Lição 4
Disponível

1. NotSerializableException: quando a coleção não quer ser serializada

O erro mais comum e mais traiçoeiro na serialização de coleções — é java.io.NotSerializableException. Ele ocorre se pelo menos um elemento da coleção não implementa a interface Serializable.

Vamos ver um exemplo ingênuo:

import java.io.*;
import java.util.*;

class Book {
    String title;
    Book(String title) { this.title = title; }
}

public class LibraryApp {
    public static void main(String[] args) throws Exception {
        List<Book> books = new ArrayList<>();
        books.add(new Book("Dombey e Filho"));

        // Tentativa de serializar a coleção
        try (ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("books.ser"))) {
            oos.writeObject(books); // BUM! NotSerializableException
        }
    }
}

O que vai acontecer? Na etapa oos.writeObject(books) você receberá a exceção:

java.io.NotSerializableException: Book

Por quê? Porque a classe Book não implementa a interface Serializable. Mesmo que a própria coleção (ArrayList) saiba ser serializada, os elementos da coleção precisam ser serializáveis!

Como diagnosticar

Na mensagem de erro sempre está indicada a classe que causou o problema — procure-a na mensagem da exceção. Se a coleção for grande e o erro ocorrer apenas em determinadas condições, é possível que algum elemento tenha sido adicionado por engano e não implemente Serializable.

Como corrigir

Adicione implements Serializable à sua classe:

class Book implements Serializable {
    String title;
    Book(String title) { this.title = title; }
}

Dica: Se a coleção contiver diferentes tipos de objetos, verifique todos eles quanto à conformidade com Serializable!

2. ClassCastException na desserialização: quando os genéricos pregam peças

Em Java, a informação sobre os parâmetros genéricos das coleções é apagada após a compilação (type erasure). Isso significa que, se você serializou um List<String>, mas desserializa como List<Integer>, o compilador não perceberá o erro, porém em tempo de execução você terá um ClassCastException.

Exemplo:

// Serialização
List<String> names = Arrays.asList("Anna", "Boris");
try (ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("names.ser"))) {
    oos.writeObject(names);
}

// Desserialização (PERIGOSO!)
try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream("names.ser"))) {
    List<Integer> numbers = (List<Integer>) ois.readObject(); // unchecked cast
    Integer first = numbers.get(0); // BUM! ClassCastException
}

Erro:

java.lang.ClassCastException: class java.lang.String cannot be cast to class java.lang.Integer

Como evitar

  • Não use coleções de tipo bruto (raw types) e não faça casts sem necessidade.
  • Verifique os tipos dos elementos após a desserialização, se não tiver certeza do conteúdo.
  • Documente qual tipo de coleção é serializado e o que é esperado na leitura.

Exemplo de desserialização segura:

Object obj = ois.readObject();
if (obj instanceof List<?>) {
    List<?> list = (List<?>) obj;
    if (!list.isEmpty() && list.get(0) instanceof String) {
        @SuppressWarnings("unchecked")
        List<String> safeNames = (List<String>) obj; // warning suprimido, mas o tipo foi verificado!
    }
}

3. Alteração da estrutura de classes: serialVersionUID e compatibilidade com versões anteriores

Você serializou uma coleção e depois decidiu adicionar um novo campo na classe do elemento, mudar o nome de um campo ou até alterar a estrutura da classe. Agora, ao tentar desserializar o arquivo antigo, você obterá um erro enigmático:

java.io.InvalidClassException: Book; local class incompatible: stream classdesc serialVersionUID = 1234, local class serialVersionUID = 5678

Por que isso acontece

Cada classe serializável recebe um identificador de versão exclusivo — serialVersionUID. Se a classe mudou (por exemplo, você adicionou um campo), a JVM calcula um novo serialVersionUID, e a desserialização percebe que a versão da classe não coincide com a que existia na serialização.

Como evitar

  • Declare explicitamente o serialVersionUID em suas classes:
class Book implements Serializable {
    private static final long serialVersionUID = 1L;
    String title;
    // ...
}
  • Mantenha compatibilidade com versões anteriores: não remova nem renomeie campos se planeja ler arquivos antigos.
  • Teste a desserialização após alterações.

O que fazer se você realmente precisar alterar a classe?

  • Considere implementar os métodos readObject/writeObject para controlar a serialização manualmente.
  • Ou migre os dados: leia o arquivo antigo com a versão antiga da classe e depois salve novamente no novo formato.

4. Perda de dados na serialização de coleções imutáveis

Nas versões mais recentes do Java, surgiram coleções imutáveis, por exemplo, criadas via List.of(), Set.of(), Map.of(). Em versões antigas do Java (antes da 12) e em algumas implementações de terceiros, a serialização dessas coleções pode não funcionar corretamente: após a desserialização, a coleção se torna mutável comum ou até ocorre um erro.

Exemplo:

List<String> list = List.of("a", "b", "c");
try (ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("list.ser"))) {
    oos.writeObject(list);
}

Em JVMs antigas, na desserialização ocorria um erro ou a coleção deixava de ser imutável.

Como evitar

  • Verifique a documentação da versão do Java que você utiliza.
  • Teste a serialização e desserialização dessas coleções.
  • Se precisar manter a imutabilidade, após a desserialização, envolva a coleção com Collections.unmodifiableList(list).

5. Serialização de campos transient e static

O que acontece com esses campos:

  • transient — campos marcados com essa palavra-chave não são serializados. Após a desserialização, terão o valor padrão (por exemplo, null ou 0).
  • static — campos de classe (e não de objeto) nunca são serializados.

Exemplo:

class Book implements Serializable {
    String title;
    transient String cache; // não é serializado!
    static String publisher = "Default"; // também não é serializado!
}

Por que isso é importante

Se você armazena alguns valores computados ou cache dentro do objeto, marque-os como transient — isso economiza espaço e acelera a serialização.

Atenção: Após a desserialização, os campos transient precisam ser recalculados ou inicializados novamente.

6. Serialização de coleções grandes: desempenho e tamanho do arquivo

Problemas:

  • Coleções grandes (por exemplo, um milhão de objetos) podem levar a arquivos enormes, tempos longos de gravação e leitura e, às vezes, até falta de memória (OutOfMemoryError).
  • Ao serializar um grafo de objetos (por exemplo, coleções complexas inter-relacionadas), o tamanho do arquivo pode crescer inesperadamente.

Como evitar

  • Serialize a coleção em partes: por exemplo, grave os objetos um a um ou em pequenos lotes.
  • Use processamento em streaming: em vez de serializar a coleção inteira de uma vez, serialize os elementos conforme a necessidade.
  • Compacte os arquivos: use GZIPOutputStream para reduzir o tamanho do arquivo.

Exemplo de serialização em streaming:

try (ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("books.ser"))) {
    for (Book book : bigList) {
        oos.writeObject(book);
    }
}

Atenção: Nessa abordagem, a desserialização requer saber quantos objetos foram gravados (ou usar um “marcador de fim” especial).

1
Tarefa
JAVA 25 SELF, nível 44, lição 4
Bloqueado
Interpretação incorreta dos dados: `ClassCastException` após desserialização 🚨
Interpretação incorreta dos dados: `ClassCastException` após desserialização 🚨
1
Tarefa
JAVA 25 SELF, nível 44, lição 4
Bloqueado
Arquivista digital: armazenamento eficiente de grandes volumes de dados com compressão 🗄️
Arquivista digital: armazenamento eficiente de grandes volumes de dados com compressão 🗄️
1
Pesquisa/teste
Serialização de estruturas complexas, nível 44, lição 4
Indisponível
Serialização de estruturas complexas
Serialização de estruturas complexas
Comentários
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION