Dúvida em uma Questão

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