Gente tenho estudado para a certificação SCJP 5.0 e fiquei com uma grande dúvida em uma questão.
A questão é do capítulo 3 (página 152) do livro da kathy.
class CardBoard{
Short story = 5;
CardBoard go(CardBoard cb){
cb = null;
return cb
}
public static void main(String[] args){
CardBoard c1 = new CardBoard();
CardBoard c2 = new CardBoard();
CardBoard c3 = c1.go(c2);
c1 = null;
//FAZ ALGO
}}
Quando a execução chegar a //FAZ ALGO, quantos objetos estarão qualificados para a coleta de lixo?
RESPOSTA: 2
A resposta dada pelo livro foi que somente o objeto c1 está apto e como ele possui um objeto Short dentro dele este também estaria apto para a coleta.
Fiquei na dúvida pelo fato de eu ter lido que quando um objeto é passado como argumento para um método é utilziado a mesma referencia do objeto passdo, entao pensei, se o método c1.go passa um objeto e c2 e dentro do método o objeto é anulado achei q assim o objeto c2 também estaria nulo.
Além disso pensei q como o método go utiliza return cb e o objeto cb está nulo o c3 também estaria nulo.
Gostaria de saber o porque de somente o c1 estar nulo.
Alguém poderia me dar uma ajuda?
[RESPOSTA====]
No momento em que o método c1.go é chamado passando a referência a c2 isso faz com que go tenha controle para alterar o objeto c2 mas de acordo com a regra geral o método chamado não pode fazer com que a referência passada aponte para um novo objeto e nem nulo, ou seja, no momento em que a linha cb = null; é executada isso faz com que cb seja uma cópia totalmente desvinculada do objeto real. Caso fosse alterado somente um objeto de c2 sem anula-lo isso se refleteria no objeto c2 original.
Ficou meio embolado mas qualquer coisa perguntem q tento explicar melhor.
[quote=“lcm4693”]
Fiquei na dúvida pelo fato de eu ter lido que quando um objeto é passado como argumento para um método é utilziado a mesma referencia do objeto passdo, entao pensei, se o método c1.go passa um objeto e c2 e dentro do método o objeto é anulado achei q assim o objeto c2 também estaria nulo.[/quote]
O objeto tem 2 referências: c2 e cb. Você removeu cb, mas c2 continou lá.
[quote=“lcm4693”]
Além disso pensei q como o método go utiliza return cb e o objeto cb está nulo o c3 também estaria nulo.[/quote]
Nunca existiu um terceiro:
CardBoard c1 = new CardBoard(); // 2 objetos
CardBoard c2 = new CardBoard(); // Mais 2 objetos
CardBoard c3 = null; // Nenhum objeto
Edit: É mais fácil resolver essas questões desenhando. Faz uma bolinha pra cada objeto, uma bolona para o heap e uma seta pra cada referência. Daí, vai riscando as setas ou colocando novas.
Certo, até entendi seu ponto de vista…
Mas quando a linha é executada:
CardBoard c3 = c1.go(c2);
está sendo executado o método go do objeto c1 passando o objeto c2 como parâmetro, certo?
Quando é feita essa passagem o método go recebe a referência do objeto que foi passada, sendo assim, dentro do método terá um objeto que apontará para o mesmo objeto que c2 aponta, né não?
E dentro desse método esse objeto (utilizado no argumento) é setado como nulo… Aí pensei que como objeto que c2 e que o argumento aponta está nulo ISSO QUER DIZER Q C2 está nulo, certo???
Não é assim q funciona não?
[quote]E dentro desse método esse objeto (utilizado no argumento) é setado como nulo… Aí pensei que como objeto que c2 e que o argumento aponta está nulo ISSO QUER DIZER Q C2 está nulo, certo???
Não é assim q funciona não?[/quote]
Não!
Parametros de metodos nunca são passados como referencia, sempre como valor, portanto, o que é passado para o metodo go() é uma copia do valor da variavel c2, a partir do momento que entra no metodo, existem duas variaveis distintas, c2 e cb, as duas possuem o mesmo valor (a referencia para o objeto), pois uma é copia da outra, mas são distintas e a alteração em uma não altera a outra. Note que estou falando do valor da variavel, não do objeto, uma alteração no OBJETO referenciado por cb tambem altera o OBJETO c2, se as duas possuem o mesmo valor (referencia).
Veja um exemplo:
[code]public void metodo(String y){
y = "alterado";
System.out.println(y);
}
String x = "original";
metodo(x);
System.out.println(x);[/code]
Este programa imprime:
alterado
original
pois ao alterar a variavel y, a x não é alterada, pois y é uma copia da referencia de x, não a propria variavel x.
Só tem um problema…
No livro da khaty segue esse exempolo aí
import java.awt.Dimension;
public class ReferenceTest {
public static void main(String[] args){
Dimension d = new Dimension(5,10);
ReferenceTest rt = new ReferenceTest();
System.out.println("Antes do Modify " + d.height);
rt.modify(d);
System.out.println("Depois do Modify " + d.height);
}
void modify(Dimension dim){
dim.height = dim.height + 1;
System.out.println("dim dentro do modify = " + dim.height);
}
}
Os valores exibidos serão:
Antes do Modify 10
dim dentro do modify = 11
Depois do Modify 11
Isso quer dizer que ele passou a referência para o método e dentro desse método foi alterado o próprio objeto… Li no livro que com tipos primitivos são passadas cópias totalmente desvinculadas do valor original será que acontece o mesmo com strings? Pois como podem ver com objetos o valor passado é a referência ao objeto…
Alguém pode me ajudar? Agora fiquei confuso
Entendi…
A regra geral é que você pode alterar o estado de um objeto mas se fizer a variável recebida apontar para um novo objeto isso não afeta a variável que foi passada.
Como no exemplo a seguir:
public static void main(String[] args){
Dimension d = new Dimension(5,10);
ReferenceTest rt = new ReferenceTest();
System.out.println("Antes do Modify " + d.height);
rt.modify(d);
System.out.println("Depois do Modify " + d.height);
}
void modify(Dimension dim){
dim = new Dimension(70,6);
dim.height = dim.height + 1;
System.out.println("dim dentro do modify = " + dim.height);
}
}
Desta vez dentro do método modify estou atribuindo um novo objeto à variável dim e isso não faz com que a variável “d” (que foi passada no método) seja alterada.
O exemplo das strings deram diferentes pq quando o valor “alterado” é atribuído a y isso faz com que y aponte para um novo objeto e por isso não há alteração no objeto original.
Alguém poderia confirmar se é isso mesmo?
As variáveis são sempre passadas por valor.
Ocorre que aquelas que referenciam objetos contêm o endereço do objeto na memória, não o objeto em si.
Ou seja, quando é passada uma cópia da variável, a cópia referencia o mesmo objeto. São 2 referências para o mesmo objeto.
String é objeto, mas é imutável.
Claro com certeza o q é passado é a referência ao objeto…
ENTENDI!
MUITO OBRIGADO GALERA