1. Serialização de coleções
Boa notícia: quase todas as coleções padrão do Java (por exemplo, ArrayList, HashSet, HashMap e suas “amigas”) já implementam Serializable. Isso significa que você pode serializá-las prontas para uso, sem malabarismos complicados.
Exemplo:
import java.io.Serializable;
import java.util.ArrayList;
public class MyList extends ArrayList<String> implements Serializable {
// Você pode nem escrever nada — ArrayList já é Serializable!
}
Na prática, você geralmente serializa coleções padrão, e tudo funciona sem complicações extras.
Como serializar uma coleção?
Para serializar uma coleção, usa-se a mesma abordagem que para qualquer outro objeto:
- Crie a coleção.
- Grave-a em um arquivo via ObjectOutputStream.
- Leia de volta via ObjectInputStream.
Exemplo 1: Serialização ArrayList<String>
import java.io.*;
import java.util.*;
public class SerializeListDemo {
public static void main(String[] args) throws Exception {
// 1. Criamos uma lista de strings
List<String> books = new ArrayList<>();
books.add("O Apanhador no Campo de Centeio");
books.add("Grandes Esperanças");
books.add("A Divina Comédia");
// 2. Salvamos a lista em um arquivo
ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("books.ser"));
out.writeObject(books);
out.close();
// 3. Lemos a lista de volta do arquivo
ObjectInputStream in = new ObjectInputStream(new FileInputStream("books.ser"));
List<String> loadedBooks = (List<String>) in.readObject();
in.close();
// 4. Verificamos o resultado
System.out.println("Lista de livros após a desserialização:");
for (String book : loadedBooks) {
System.out.println("- " + book);
}
}
}
Saída:
Lista de livros após a desserialização:
- O Apanhador no Campo de Centeio
- Grandes Esperanças
- A Divina Comédia
Exemplo 2: Serialização de HashSet<Integer>
Set<Integer> numbers = new HashSet<>(Arrays.asList(10, 20, 30, 40));
ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("numbers.ser"));
out.writeObject(numbers);
out.close();
ObjectInputStream in = new ObjectInputStream(new FileInputStream("numbers.ser"));
Set<Integer> loadedNumbers = (Set<Integer>) in.readObject();
in.close();
System.out.println("Conjunto após a desserialização: " + loadedNumbers);
Exemplo 3: Serialização de HashMap<String, Integer>
Map<String, Integer> scores = new HashMap<>();
scores.put("Alice", 100);
scores.put("Bob", 80);
ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("scores.ser"));
out.writeObject(scores);
out.close();
ObjectInputStream in = new ObjectInputStream(new FileInputStream("scores.ser"));
Map<String, Integer> loadedScores = (Map<String, Integer>) in.readObject();
in.close();
System.out.println("Mapa após a desserialização: " + loadedScores);
Pontos importantes
A ordem é preservada?
- Para List (por exemplo, ArrayList) a ordem dos elementos é sempre preservada.
- Para Set (HashSet) a ordem não é garantida (tanto antes quanto depois da serialização).
- Para Map (HashMap) a ordem dos pares chave-valor não é garantida (se precisar de ordem — use LinkedHashMap).
Coleções vazias se serializam e desserializam sem problemas. Após a desserialização, você obterá uma lista/conjunto/mapa vazio.
Coleções aninhadas (por exemplo, List<List<String>>) são serializadas corretamente se todos os elementos aninhados forem serializáveis.
2. Requisitos para os elementos da coleção
É aqui que costuma estar a primeira armadilha séria!
Todos os elementos da coleção também devem ser serializáveis.
Se pelo menos um elemento da coleção não implementa a interface Serializable, a serialização da coleção terminará com o erro NotSerializableException. E, se a coleção for grande e o erro estiver em algum lugar lá dentro, encontrar o culpado vira uma caça ao tesouro.
Exemplo: serializando uma coleção com um objeto não serializável
import java.io.*;
import java.util.*;
class NotSerializableClass {
int value;
public NotSerializableClass(int value) {
this.value = value;
}
}
public class NotSerializableDemo {
public static void main(String[] args) throws Exception {
List<Object> list = new ArrayList<>();
list.add("Hello");
list.add(new NotSerializableClass(123)); // <- Opa!
ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("badlist.ser"));
try {
out.writeObject(list); // Uma exceção será lançada aqui!
} catch (NotSerializableException e) {
System.out.println("Erro de serialização: " + e);
}
out.close();
}
}
Resultado:
Erro de serialização: java.io.NotSerializableException: NotSerializableClass
O que fazer?
A solução é simples: todos os elementos da coleção devem ser tipos padrão, como String ou Integer, ou suas próprias classes que implementem a interface Serializable. Se alguma classe não for serializável, basta adicionar a ela implements Serializable, e o problema estará resolvido.
3. Particularidades da serialização de diferentes coleções
A ordem dos elementos é preservada?
- List: Sim, a ordem dos elementos é preservada.
- Set: Depende da implementação. Em HashSet a ordem não é garantida, já em LinkedHashSet — é preservada.
- Map: Em HashMap a ordem não é garantida, em LinkedHashMap — é preservada a ordem de inserção.
Demonstração:
List<String> list = Arrays.asList("A", "B", "C");
Set<String> set = new HashSet<>(list);
ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("coll.ser"));
out.writeObject(list);
out.writeObject(set);
out.close();
ObjectInputStream in = new ObjectInputStream(new FileInputStream("coll.ser"));
List<String> loadedList = (List<String>) in.readObject();
Set<String> loadedSet = (Set<String>) in.readObject();
in.close();
System.out.println("List: " + loadedList); // sempre [A, B, C]
System.out.println("Set: " + loadedSet); // pode ser [A, C, B] etc.
Serialização de coleções vazias
Coleções vazias são serializadas sem problemas. Após a desserialização, você obterá um objeto vazio do tipo necessário.
Serialização de coleções aninhadas
É possível serializar coleções que contêm outras coleções:
List<List<String>> table = new ArrayList<>();
table.add(Arrays.asList("row1-col1", "row1-col2"));
table.add(Arrays.asList("row2-col1", "row2-col2"));
// Serialização
ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("table.ser"));
out.writeObject(table);
out.close();
// Desserialização
ObjectInputStream in = new ObjectInputStream(new FileInputStream("table.ser"));
List<List<String>> loadedTable = (List<List<String>>) in.readObject();
in.close();
System.out.println(loadedTable);
4. Exemplo prático: serializando uma coleção de objetos de uma classe própria
Vamos escrever juntos um pequeno aplicativo para uma “biblioteca virtual”, em que vamos serializar uma lista de livros. A classe Book deve ser serializável!
import java.io.*;
import java.util.*;
class Book implements Serializable {
private static final long serialVersionUID = 1L; // para compatibilidade entre versões da classe
String title;
String author;
int year;
public Book(String title, String author, int year) {
this.title = title;
this.author = author;
this.year = year;
}
@Override
public String toString() {
return title + " (" + author + ", " + year + ")";
}
}
public class LibraryApp {
public static void main(String[] args) throws Exception {
List<Book> books = new ArrayList<>();
books.add(new Book("O Apanhador no Campo de Centeio", "J. D. Salinger", 1951));
books.add(new Book("Grandes Esperanças", "Charles Dickens", 1861));
books.add(new Book("A Divina Comédia", "Dante Alighieri", 1320));
// Salvamos a lista em um arquivo
ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("mylibrary.ser"));
out.writeObject(books);
out.close();
// Lemos a lista de volta
ObjectInputStream in = new ObjectInputStream(new FileInputStream("mylibrary.ser"));
List<Book> loadedBooks = (List<Book>) in.readObject();
in.close();
System.out.println("Livros do arquivo:");
for (Book b : loadedBooks) {
System.out.println("- " + b);
}
}
}
5. Erros comuns ao serializar coleções
Erro nº 1: NotSerializableException em um elemento da coleção. Se pelo menos um elemento da coleção não for serializável, a serialização “vai falhar” com o erro NotSerializableException. Por exemplo, se você acidentalmente adicionou à coleção um objeto que não implementa Serializable ou se esqueceu de adicionar essa interface à sua classe.
Erro nº 2: Alterar a classe entre a serialização e a desserialização. Se você serializou uma coleção de objetos e depois mudou a estrutura da classe (por exemplo, adicionou ou removeu campos), durante a desserialização pode ocorrer a exceção InvalidClassException. Para evitar isso, use o campo serialVersionUID na classe.
Erro nº 3: Serializar uma coleção com campos transient ou static. Campos marcados como transient ou static não são serializados. Se seus objetos dependem desses campos, após a desserialização eles terão valores padrão (por exemplo, null ou 0).
Erro nº 4: Serializar coleções com objetos aninhados não serializáveis. Se na coleção houver coleções aninhadas ou objetos que não implementam Serializable, o erro surgirá no nível mais profundo — nem sempre fica claro onde procurar o problema. Verifique todos os níveis de aninhamento!
Erro nº 5: Desempenho com coleções grandes. Se a coleção for muito grande, a serialização pode levar muito tempo e ocupar muito espaço em disco. Nesses casos, considere a serialização em fluxo (streaming) ou a divisão da coleção em partes.
GO TO FULL VERSION