Dúvida sobre defaultReadObject e defaultWriteObject

10 respostas
jbjares

Olá pessoal,

Lendo o Livro da K.Sierra entendi que para que a serialização funcione corretamente para objetos de classes que não implementam serializable é necessário criar dois métodos com exatamente esta assinatura:

para escrita:

private void writeObject(ObjectOutputStream out) {//codigo...}

para leitura:

private void readObject(ObjectInputStream in) {//codigo...}

Até aí tudo bem. Mas eu lí também que para que os dois funcionem em sincronia seria necessário chamar respectivamente os dois métodos: out.defaultWriteObject(); e
in.defaultReadObject();

private void writeObject(ObjectOutputStream out) {out.defaultWriteObject(); //codigo...}   
private void readObject(ObjectInputStream in) {in.defaultReadObject();//codigo...}

Sendo que resolvendo uma questão do testKiller me deparei com um código que não chamava nem um dos dois métodos dentro dos métodos writeObject e readObject. Daí achei estranho e fui testar. Verifiquei que de fato a serialização funciona normal caso as duas chamadas sejam omitidas dos dois métodos, mas se um dos métodos fizer a chamada o outro terá que fazer também, caso contrário é lançada a exceção:

Exception in thread "main" java.io.EOFException
	at java.io.ObjectInputStream$BlockDataInputStream.readFully(Unknown Source)

Ou seja se não chamar o defaultXXXObject em nenhum dos dois métodos tudo funciona normal, Se chamar nos dois tudo funciona normal também mas se um fizer a chamada e outro não gera essa exceção. E essa história toda me deixou cheio de duvidas com relação a esses métodos. Alguém saberia me dizer para que de fato eles servem e o porque desse comportamento?

10 Respostas

jbjares

Para reforçar o assunto acrescento uma outra questão do testKiller que achei estranha:

Given:
10. public class Foo implements java.io.Serializable {
11. private int x;
12. public int getX() { return x; }
12.publicFoo(int x){this.x=x; }
13. private void writeObject( ObjectOutputStream s)
14. throws IOException {
15. // insert code here
16. }
17. }
Which code fragment, inserted at line 15, will allow Foo objects to be
correctly serialized and deserialized?
A. s.writeInt(x);
B. s.serialize(x);
C. s.writeObject(x);
D. s.defaultWriteObject();

Minha dúvida é a seguinte: Se a classe já implementa Serializable porque ainda tem que possuir esse método writeObject sem nem referencia a um outro Objeto ela possui?

D

No livro da Kathy ela cita estes metódos defaultXXXObject, são necessarios quando vc quer salvar uma transient. Na deserialização vc leria esta variavel e em seguida atribuiram a esta instância.
Me corrijam se estiver errado.

jbjares

Certo Daniel… mas talvez não tenha ficado claro. O que eu quero saber é porque mesmo sem chamar esses métodos defaultXXXObject dentro dos métodos readObject e writeObject a serialização dos transients ocorre sem nenhum problema?. A outra dúvida é refrente a questão do testKiller citada nos posts acima, porque é feita a pergunta de qual método deve ser usado para que a serialização ocorra normalmente se não existe Objetos transients?

Nykolas_Lima

funciona assim…

as vezes tem uma variavel int de um objeto que voce faz referencia que nao pode ser serializada pelo método convencional…

entao voce sobrescreve o writeobject e por la writeInt por exemplo…

só que fazendo isso, voce só gravou o int, e voce nao quer gravar só o int…voce quer gravar o int que nao é possivel de fazer pela serialização padrao e o resto do objeto.

entao apos gravar o int voce chama o defaultWriteObject que vai fazer a serialização padrao do resto do objeto…

nao sei se fui bastante claro…qualquer coisa pergunte…

Nykolas_Lima

jbjares:
Para reforçar o assunto acrescento uma outra questão do testKiller que achei estranha:

Given:
10. public class Foo implements java.io.Serializable {
11. private int x;
12. public int getX() { return x; }
12.publicFoo(int x){this.x=x; }
13. private void writeObject( ObjectOutputStream s)
14. throws IOException {
15. // insert code here
16. }
17. }
Which code fragment, inserted at line 15, will allow Foo objects to be
correctly serialized and deserialized?
A. s.writeInt(x);
B. s.serialize(x);
C. s.writeObject(x);
D. s.defaultWriteObject();

Minha dúvida é a seguinte: Se a classe já implementa Serializable porque ainda tem que possuir esse método writeObject sem nem referencia a um outro Objeto ela possui?

se nao me engano aqui a resposta é a D nao é?

ele só poe o método writeObject para confundir…

porque nao há nenhuma restrição para que o objeto nao possa ser serializado da forma normal…
e como ele nao sobrescreve o readObjeto também…se voce usar por exemplo um writeInt ele nao sabera como desserializar…

entao voce chamaria a defaultWriteObject que faria a serialização normal do objeto…

jbjares

hum… bacana Frango :slight_smile: Mas alguem saberia me dizer o por que esses dois métodos readObjetc e writeObject funcionam normalmente mesmo sem a chamada dos defaultxxxObject ?

L

Assim,

o defaultWriteObject() e o defaultReadObject() são métodos que fazem a serialização normal do método. Quando você os invoca, está querendo dizer: chama a serialização normal do Java, eu só estou interessado em serializar manualmente esses poucos atributos marcados como transient.

Agora, você não precisa invocar os dois métodos, e aí você está querendo dizer: eu não me importo com a serialização normal do Java, eu vou fazer toda a serialização desse objeto sozinho.

Claro, tanto writeObject() e readObject() devem ser espelhos um do outro. Se você escreve algo em um, que não é lido do outro, alguma exceção ocorre.

jbjares

Valeu Leonardo… é isso mesmo. :slight_smile: Você sabe onde mais esses métodos podem ser utilizados ou pelomenos para a prova em quais outros contextos eles podem ser cobrados?

L

É só na serialização mesmo.

jbjares

Valeu Leonardo3001 :slight_smile:

Criado 21 de março de 2009
Ultima resposta 22 de mar. de 2009
Respostas 10
Participantes 4