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]
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.
Quando um objeto é desserializado, as variáveis estáticas continuaram a ser as mesmas de antes da desserialização.
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.
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)
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.