Fazia bastante tempo que eu não lia um capítulo da SCJP 6, mas como eu preciso retomar meus estudos, então, por tabela, tammbém preciso retomar minhas anotações/posts sobre o que eu andar lendo...
Você, estagiário (não tenho saudades dessa época), vai se lembrar de serialização quando estiver desenvolvendo alguma aplicação web, por exemplo. Eu nunca havia feito serialização manualmente até o momento em que eu li essa seção do livro da SCJP 6.
Execute esse código e abra o arquivo Pessoa.txt só por curiosidade. Note que você consegue entender parte do que foi escrito apenas por mera casualidade, pois o Java deve utilizar uma estrutura bem formada para organizar os dados de um objeto num arquivo.
Agora, vamos complicar. E se eu quiser que uma das variáveis de instância da classe Pessoa seja uma referência a outro objeto? Insira no código acima a classe Contato:
Modifique a classe Pessoa:
E a classe Principal também:
Agora tente executar novamente. Conseguiu? Eu acho que não...
Como você pode ver, o programa não consegue serializar a propriedade dadosContrato da classe Pessoa, porque a classe Contrato não é serializavel. Você conseguiria resolver esse problema, fazendo a classe Contrato implementar Serializable, mas e se não tiver acesso ao seu código fonte?
Incluindo o modificador de acesso transient à propriedade dadosContrato de Pessoa, você não salva o seu estado quando serializar a instância de Pessoa, acabando com o erro em tempo de execução. Entretanto, vale lembrar que nenhum construtor da classe a ser serializada é chamado, muito menos os valores atribuidos em tempo de declaração das variáveis de instância são usados, o que significa que as variáveis transientes são inicializadas com valores default.
Para testar isso, tente serializar a classe abaixo:
Mas e se for justamente salvar esta propriedade não serializável o que você precisa?
Você pode, além de fazer esta propriedade virar transient, implementar um par de métodos na sua classe Pessoa, para serializar você mesmo os dados de Contato durante a serialização de Pessoa. Altere a classe Pessoa conforme código abaixo:
Acho que agora você consegue executar o programa.
Tá quase acabando, prometo :D Vimos que nenhum construtor da classe serializavel é executado. Vimos que variaveis transientes não são salvas. Vimos como serializar uma propriedade não serializável. Mas e quando a super classe não for serializável? E quanto às variáveis estáticas?
Bem, variáveis estáticas não correspondemm ao estado do objeto (instância da classe) em si. Perceba que todas as instâncias de uma classe compartilham o mesmo valor de uma variável estatica. Que sentido faria salvá-la? E se duas ou mais instâncias de uma classe fossem salvas, qual valor para a variável estática seria utilizado?
Quanto à super classe não serializável... Bem, dissemos que o construtor da classe serializável não é chamado, nem as variáveis de instância são inicializadas com os valores descritos em tempo de declaração. Mas o construtor da primeira classe não serializável é chamado, que chama o construtor da sua super classe, e assim por diante. Quer tirar a dúvida?

Esta obra está licenciada sob uma Licença Creative Commons.
Em Ciência da Computação, no contexto de armazenamento e transmissão de dados, a serialização é o processo de salvar um objeto em um meio de armazenamento (como um arquivo de computador ou um buffer de memória) ou transmiti-lo por uma conexão de rede, seja em forma binária ou em formato de texto como o XML. Esta série de bytes pode ser usada para recriar um objeto com o mesmo estado interno que o original. [Wikipedia]
Você, estagiário (não tenho saudades dessa época), vai se lembrar de serialização quando estiver desenvolvendo alguma aplicação web, por exemplo. Eu nunca havia feito serialização manualmente até o momento em que eu li essa seção do livro da SCJP 6.
import java.util.*;
import java.io.*;
class Pessoa implements Serializable {
private String nome;
public Pessoa (String nome){
this.nome = nome;
}
public String getNome() {
return this.nome;
}
public void setNome(String nome){
this.nome = nome;
}
public String toString() {
String result = "nome: " + this.nome;
return result;
}
}
public class Principal {
public static void main(String[] args){
Pessoa pessoa = new Pessoa("Leandro");
String fileName = Pessoa.class.getName() + ".txt";
System.out.println("Antes da serialização - "
+ pessoa);
serializeObject(fileName, pessoa);
Pessoa pessoaNova =
(Pessoa) deserializeObject(fileName);
System.out.println("Depois da serialização - "
+ pessoaNova);
}
public static void serializeObject(
String fileName,
Object object){
try {
FileOutputStream fos =
new FileOutputStream(fileName);
ObjectOutputStream oos =
new ObjectOutputStream(fos);
oos.writeObject(object);
oos.close();
} catch (Exception ex){
ex.printStackTrace();
}
}
public static Object deserializeObject(String fileName){
Object object = null;
try {
FileInputStream fis =
new FileInputStream(fileName);
ObjectInputStream ois =
new ObjectInputStream(fis);
object = ois.readObject();
ois.close();
} catch (Exception ex){
ex.printStackTrace();
}
return object;
}
}
Execute esse código e abra o arquivo Pessoa.txt só por curiosidade. Note que você consegue entender parte do que foi escrito apenas por mera casualidade, pois o Java deve utilizar uma estrutura bem formada para organizar os dados de um objeto num arquivo.
Agora, vamos complicar. E se eu quiser que uma das variáveis de instância da classe Pessoa seja uma referência a outro objeto? Insira no código acima a classe Contato:
class Contato {
private String telefone;
Contato(String telefone){
this.telefone = telefone;
}
public String getTelefone(){
return this.telefone;
}
public void setTelefone(String telefone){
this.telefone = telefone;
}
public String toString() {
String result = "telefone: " + telefone;
return result;
}
}
Modifique a classe Pessoa:
class Pessoa implements Serializable {
private String nome;
private int idade;
private Contato dadosContato;
Pessoa (
String nome,
int idade,
Contato dadosContato){
this.nome = nome;
this.idade = idade;
this.dadosContato = dadosContato
}
...
public int getIdade() {
return this.idade;
}
public void setIdade(int idade){
this.idade = idade;
}
public Contato getDadosContato() {
return this.dadosContato;
}
public void setDadosContato(Contato dadosContato){
this.dadosContato = dadosContato;
}
public String toString() {
String result = "nome: " + this.nome + "\n";
result += "idade: " + this.idade + "\n";
result += "contato - " + this.dadosContato;
return result;
}
}
E a classe Principal também:
public class Principal {
public static void main(String[] args){
Contato dadosContato = new Contato("9876-5432");
Pessoa pessoa =
new Pessoa("Leandro",23, dadosContato);
}
...
}
Agora tente executar novamente. Conseguiu? Eu acho que não...
Como você pode ver, o programa não consegue serializar a propriedade dadosContrato da classe Pessoa, porque a classe Contrato não é serializavel. Você conseguiria resolver esse problema, fazendo a classe Contrato implementar Serializable, mas e se não tiver acesso ao seu código fonte?
Incluindo o modificador de acesso transient à propriedade dadosContrato de Pessoa, você não salva o seu estado quando serializar a instância de Pessoa, acabando com o erro em tempo de execução. Entretanto, vale lembrar que nenhum construtor da classe a ser serializada é chamado, muito menos os valores atribuidos em tempo de declaração das variáveis de instância são usados, o que significa que as variáveis transientes são inicializadas com valores default.
Para testar isso, tente serializar a classe abaixo:
class Teste implements Serializable{
private transient int numero = 42;
private String texto;
Teste() {
this.numero = 25;
this.texto = "Mais um teste";
}
Teste(String texto, int numero){
this.texto = texto;
this.numero = numero;
}
public String getTexto() {
return this.texto;
}
public void setTexto(String texto){
this.texto = texto;
}
public int getNumero() {
return this.numero;
}
public void setNumero(int numero){
this.numero = numero;
}
public String toString(){
String result = "texto: " + this.texto + "\n";
result += "numero: " + this.numero;
return result;
}
}
Mas e se for justamente salvar esta propriedade não serializável o que você precisa?
Você pode, além de fazer esta propriedade virar transient, implementar um par de métodos na sua classe Pessoa, para serializar você mesmo os dados de Contato durante a serialização de Pessoa. Altere a classe Pessoa conforme código abaixo:
class Pessoa implements Serializable {
private String nome;
private int idade;
private transient Contato dadosContato;
...
private void writeObject(ObjectOutputStream os) {
try {
os.defaultWriteObject();
Boolean checkDadosContrato =
(this.dadosContato != null);
os.writeBoolean(checkDadosContrato);
if (checkDadosContrato) {
os.writeObject(this.dadosContato
.getTelefone());
}
} catch (Exception ex){
ex.printStackTrace();
}
}
private void readObject(ObjectInputStream is) {
try {
is.defaultReadObject();
Boolean checkDadosContrato =
is.readBoolean();
if (checkDadosContrato) {
String telefone = (String) is.readObject();
this.dadosContato = new Contato(telefone);
}
} catch (Exception ex){
ex.printStackTrace();
}
}
Acho que agora você consegue executar o programa.
Tá quase acabando, prometo :D Vimos que nenhum construtor da classe serializavel é executado. Vimos que variaveis transientes não são salvas. Vimos como serializar uma propriedade não serializável. Mas e quando a super classe não for serializável? E quanto às variáveis estáticas?
Bem, variáveis estáticas não correspondemm ao estado do objeto (instância da classe) em si. Perceba que todas as instâncias de uma classe compartilham o mesmo valor de uma variável estatica. Que sentido faria salvá-la? E se duas ou mais instâncias de uma classe fossem salvas, qual valor para a variável estática seria utilizado?
Quanto à super classe não serializável... Bem, dissemos que o construtor da classe serializável não é chamado, nem as variáveis de instância são inicializadas com os valores descritos em tempo de declaração. Mas o construtor da primeira classe não serializável é chamado, que chama o construtor da sua super classe, e assim por diante. Quer tirar a dúvida?
class TesteBase {
private long numeroLongo = 100000L;
private String textoBase;
TesteBase() {
textoBase = "texto base";
}
TesteBase(long numeroLongo, String textoBase){
this.numeroLongo = numeroLongo;
this.textoBase = textoBase;
}
public String toString(){
String result =
"textoBase: " + this.textoBase + "\n";
result += "numeroLongo: " + this.numeroLongo;
return result;
}
}
class Teste extends TesteBase implements Serializable{
private transient int numero = 42;
private String texto;
Teste() {
this.numero = 25;
this.texto = "Mais um teste";
}
Teste(
String texto,
int numero,
long numeroLongo,
String textoBase){
super(numeroLongo,textoBase);
this.texto = texto;
this.numero = numero;
}
public String getTexto() {
return this.texto;
}
public void setTexto(String texto){
this.texto = texto;
}
public int getNumero() {
return this.numero;
}
public void setNumero(int numero){
this.numero = numero;
}
public String toString(){
String result =
"texto: " + this.texto + "\n";
result += "numero: " + this.numero + "\n";
result += super.toString();
return result;
}
}
Esta obra está licenciada sob uma Licença Creative Commons.





No comments:
Post a Comment
Regras são chatas, mas...
Todos os comentários são lidos e moderados previamente.
São publicados aqueles que respeitam as regras abaixo:
- Seu comentário precisa ter relação com o assunto do post;
- Em hipótese alguma faça propaganda de outros blogs ou sites;
- Não inclua links desnecessários no conteúdo do seu comentário;
- Se quiser deixar sua URL, comente usando a opção OpenID;
- CAIXA ALTA, miguxês ou erros de ortografia não serão tolerados;
- Ofensas pessoais, ameaças e xingamentos não são permitidos;