Serialização e contagem de instâncias

Tem um campo estático na classe que conta as instâncias. Só que ao desserializar, o construtor que incrementa a contagem não é chamado e essa contagem não fica correta. Como eu resolvo isso?

package basico.serializacao;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import common.Console;
import common.OptionParser;

public class Serializacao {
	
	private static final String FILENAME = "serializado.txt";

	public static void main(String[] args) {
		OptionParser op = new OptionParser(args, "rw");		
		if (op.optionGiven('w')) {
			Pessoa p = new Pessoa("Renato", 22);
			escrever(p);
			Console.puts("Escrevi " + p);
		}
		if (op.optionGiven('r')) 
			Console.puts("Li " + ler());
	}
	
	public static void escrever(Pessoa p) {
	    try {
			FileOutputStream fos = new FileOutputStream(FILENAME);
			ObjectOutputStream oos = new ObjectOutputStream(fos);
			oos.writeObject(p);
			oos.close();
			fos.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	
	public static Pessoa ler() {
		Pessoa p = null;
		try {
			FileInputStream fis = new FileInputStream(FILENAME);
			ObjectInputStream ois = new ObjectInputStream(fis);
			p = (Pessoa) ois.readObject();
		} catch (IOException e) {
			e.printStackTrace();
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		}
		return p;
	}

}

class Pessoa implements Serializable {
	
	String nome;
	int idade;
	static int totalPessoas = 0;
	transient int sequencia;
	
	public Pessoa(String nome, int idade) {
		this.nome = nome;
		this.idade =  idade;
		this.sequencia = ++totalPessoas;
	}
	
	@Override 
	public String toString() {
		return String.format("[%s, %d anos, sequencia=%d, total=%d]", 
			nome, idade, sequencia, totalPessoas);
	}
	
}

// OBS: na segunda linha, o total refere-se ao objeto criado na primeira
// Veja que depois da desserialização agora há duas instâncias na memória!
//
// Escrevi [Renato, 22 anos, sequencia=1, total=1]
// Li [Renato, 22 anos, sequencia=0, total=1] 
  1. Variáveis estáticas não são salvas na serialização. Isso porque variáveis estáticas são variáveis de classe e não do objeto.
  2. Quando um objeto é desserializado, as variáveis estáticas continuaram a ser as mesmas de antes da desserialização.
  3. Quando um objeto é desserializado não será criada uma nova instância do objeto. A desserialização apenas “recupera” objetos salvos em um arquivo. Por isso, o construtor não é chamado, ou melhor, o construtor já foi chamado quando a instância daquele objeto foi criado (antes de ser serializado).

Neste caso, como sequencia é transient e o construtor de Pessoa não será chamado novamente, seu valor será o padrão (0) e o valor de totalPessoas será o mesmo de antes da desserialização, ou seja, 1.

1 e 2: eu sei.
3: pelo o que eu entendi é criada uma nova instância sim, não é? A diferença é que não é pelo construtor, mesmo porque não há como advinhar qual usar, não é isso?

O ponto é: como contar as instâncias, incluindo as desserializadas?

[quote=renato3110]
O ponto é: como contar as instâncias, incluindo as desserializadas?[/quote]
Agora eu também quero saber… vou dar uma pesquisada, caso eu consiga encontrar alguma coisa volto a postar.

Implemente readObject e seja feliz. Se não souber do que se trata RTFM.

acho que vc poderia sobrescrever os métodos writeObject e readObject pra que na serialização vc pudesse resolver essa questão do static (lá vc poderia serializar seu objeto com alguma tranqueira genérica e mais legível - tipo XMLEncoder e XMLDecoder e então ler ou gravar sua váriável static sob alguma condição específica)

o que vc acha?

Woody

Não etendi se está concordando ou discordando, mas enfatizando, é criada uma nova instância sim, só não se usa o construtor.

Pois é louds, o texto que eu tava lendo parou por aí e não falou desses métodos que eu esqueci e do serialVersionUID. Sim, eu vou RTFM :smiley:

O XMLDecoder chama o construtor padrão, acho que dá pra fazer algo em cima disso nesse caso.

Pessoal, eu fiz umas classes utilitárias para serialização, olhem só:

Serializer<Pessoa> serializer = new XMLSerializer<Pessoa>("Serializando.txt");
//ou DefaultSerializer...

Pessoa p = new Pessoa("Renato", 22, 58.0f);
serializer.write(p);
p = serializer.read();

O que acham? Legalzinho? Ja´existe algo do tipo?

No caso da serialização XML acho que deu pra resolver esse lance de contar referências, eu coloquei o incremento no construtor padrão do bean.