Problema de referência de variável ao carregar um objeto de um arquivo em Java
-
27-09-2019 - |
Pergunta
Estou com um problema com a referência de uma variável ao carregar um objeto serializado salvo de um arquivo de dados.Todas as variáveis que fazem referência ao mesmo objeto não parecem ser atualizadas com a mudança.Criei um código cortado abaixo que ilustra o problema.
Tournament test1 = new Tournament();
Tournament test2 = test1;
try {
FileInputStream fis = new FileInputStream("test.out");
ObjectInputStream in = new ObjectInputStream(fis);
test1 = (Tournament) in.readObject();
in.close();
}
catch (IOException ex){
Logger.getLogger(Frame.class.getName()).log(Level.SEVERE, null, ex);
}
catch (ClassNotFoundException ex){
Logger.getLogger(Frame.class.getName()).log(Level.SEVERE, null, ex);
}
System.out.println("test1: " + test1);
System.out.println("test2: " + test2);
Depois que esse código é executado, test1 e test2 não fazem mais referência ao mesmo objeto.Que eu saiba, eles deveriam fazer isso, pois na declaração de test2 faz referência a test1.Quando test1 é atualizado, test2 deve refletir a alteração e retornar o novo objeto quando chamado no código.Estou faltando algo essencial aqui ou fui mal ensinado sobre como funcionam as referências de variáveis em Java?
Solução
Estou perdendo algo essencial aqui ou fui enganado sobre como as referências variáveis em Java funciona?
Muito provavelmente você entendeu mal o que lhe foi ensinado ou aprendeu algo errado.Todas as variáveis do tipo de referência (ou seja,tipos não primitivos) consulte directly
para um objeto.
Tournament test1 = new Tournament();
Cria uma nova instância de Tournament
e faz test1
consulte-o.
Tournament test2 = test1;
Copia a referência de test1
para test2
, fazendo com que ambos se refiram ao mesmo objeto.
test1 = (Tournament) in.readObject();
Faz test1
referem-se a um objeto diferente que foi desserializado do fluxo, enquanto test2
ainda se refere ao objeto original.
Outras dicas
Quando você desempacota um objeto com serialização e o atribui a uma variável, você substitui a referência antiga (no seu caso, um new Tournament()
) com o novo objeto..então test2
estará apontando para o original Tournament
enquanto test1
fará referência ao objeto apenas não serializado.
É como fazer:
Tournament t1 = new Tournament();
Tournament t2 = t1;
t1 = new Tournament();
vai t1 == t2
?Claro que não..
Você não está "atualizando" test1
em qualquer lugar.
Esta linha está atribuindo um diferente objeto do tipo Tournament
que está lendo o fluxo de entrada e atribuindo esse novo objeto a test1
:
test1 = (Tournament) in.readObject();
Enquanto isso, test2
ainda está apontando para o objeto original que foi alocado no início do seu bloco de código.
O problema é a noção de que Java passa e atribui por referência.Isso não acontece.Java passa e atribui por valor.Acontece que com tipos de referência, o valor passado é uma referência.
A diferença é esta:Digamos que você tenha algum código de teste
Tournament test1 = new Tournament();
Tournament test2 = test1;
test1 = new Tournament();
System.out.println(test1 == test2 ? "Equal" : "Not Equal");
Se Java passasse por referência, ele imprimiria Equal
, porque test2
seria apenas um apelido para test1
.No entanto, como o Java passa por valor, ele imprime Not Equal
.