Parâmetro por referência

Sei que é um assunto já bem “batido”, mas eu não consegui entender uma coisa… Eu sei que o java passa os parâmetros sempre por valor, o que acontece é que ele passa o valor da referência. Mas então, pq o resultado desses meus testes não têm o msm comportamento?!

Código 1:

[code] public static void main(String[] args) {

	String a = new String("Sou A");
	System.out.println(a);
	
	muda(a);
	System.out.println(a);
}

private static void muda(String s){
	s = "Sou B";		
}

[/code]Ele imprime:

[quote]Sou A
Sou A[/quote]

Código 2:

[code] public static void main(String[] args) {

	JFormattedTextField a = new JFormattedTextField("Sou A");
	System.out.println(a.getText());
	
	muda(a);
	System.out.println(a.getText());
}

private static void muda(JFormattedTextField s){
	s.setText("Sou B");		
}

[/code]
Imprime:

[quote]Sou A
Sou B[/quote]

Ok! Agora me digam, pq???

Pra mim os dois deveriam agir como o Código 2.

Fiz vários testes, fiz com que o método muda recebesse um Component (entao o resultado foi como no código 2). Então fiz com que o método recebesse um Object e o resultado foi como o do código 1. Ai permaneci com o parâmetro do tipo Object, só que invés de uma String, enviei um StringBuilder e o resultado foi como no 2.

Por favor, alguém pode me explicar isso melhor?! :cry:

Strings são objetos IMUTÁVEIS.
Mesmo vc usando a superclasse como parametro (no caso do object), continua sendo String e continua imutável…

Se eu fizesse:

String s = “java”;
s.toUpperCase();
System.out.println( s );

printaria “java”, e nao “JAVA”… s.toUpperCase() criou uma nova String, mas nao fez com que nenhuma referencia apontasse pra essa String, entao ela “se perdeu”…

Estude um poco mais a fundo REFERÊNCIAS em Java, STRINGS e POOL DE STRING que vc vai entender melhor.

no primeiro vc muda o valor de uma variavel interna do metodo
tire o valor de dentro do do metodo sete o valor com this.s = “valor”
vai ficar = no segundo metodo

o segundo vc seta o valor do objeto que foi criado dentro do metodo main, ele vai carregar esse valor para onde for desde que vc num use new ou = em cima da variavel de referencia

[quote=jjose]no primeiro vc muda o valor de uma variavel interna do metodo
tire o valor de dentro do do metodo sete o valor com this.s = “valor”
vai ficar = no segundo metodo

o segundo vc seta o valor do objeto que foi criado dentro do metodo main, ele vai carregar esse valor para onde for desde que vc num use new ou = em cima da variavel de referencia[/quote]

this num contexto static?

fala besteira nao amiguim

A minha solução foi uma merda, rs. Ignore.

Renata…

leia meu post la em cima… e ignore os outros pra nao confundir sua cabeça

renata
como eu te amo eu fiz para vc


public class AreLinda {

	static String a = new String("Sou A");
	
	 public static void main(String[] args) {  
		       
	       
	     System.out.println(a);  
	       
	     muda(a);  
	     System.out.println(a);  
	 }  
		   
	private static void muda(String s){
		
		s = "Sou B";     
              a = s; 
	} 
} 

Evite certos comentários pessoais, já houve uma discussão dessas aqui e os moderadores estão tentando evitar de virar notícia principal do Cidade Alerta.

Até!

Acho que não é nem por ser String (imutável) e afins, o que acontece é que ela atribuiu a variável s, local ao método, um novo objeto. Mesmo que não fosse String, fosse outro obj “mutável”, aconteceria a mesma coisa.

Me corrijam se eu estiver errado!

É isso mesmo. A passagem é por valor.

Em caso de objetos, onde as variáveis são referências, a referência é copiada.

Isso significa que, dentro de um método, embora seja possível alterar valores dentro do objeto referenciado, é impossível alterar para onde essa referência aponta. Se fizer isso, estará alterando só em escopo local.

Ou seja, comandos como:

s.setValue("xuz"); //Ok, s ainda aponta para o objeto fora da função

//Ops, alteramos a referência de S. 
//Isso só vale aqui dentro da função, já que fora daqui, a referência é outra.

s = new String("xyz"); 
s.setValue("xuz"); //Estamos alterando só o s criado na linha de cima.

//Também não conseguimos tornar o s fora da função nulo. 
s = null;

Só terão efeito dentro do método.

Obrigada pela ajuda meninos!

Então sic e ViniGodoy, o que vcs falaram era o que eu sabia. Concordo com o que vcs disseram, mas se de fato fosse assim, então pq no caso do JFormattedTextField não ocorreu o mesmo?!

Foi justamente por isso que eu fiquei perdida com a situação, eu esperava que com o JFormattedTextField ocorresse o mesmo, afinal, ele tb herda de Object. Mas não! No caso dele eu consigo alterar o valor como mostrei no exemplo acima.

Por esse motivo começo a achar que o que o fabiocsi explicou sobre objetos MUTÁVEIS e IMUTÁVEIS faz mais sentido. Veja só, eu testei com objetos Integer e houve o mesmo comportamento do String. No entanto, com StringBuilder houve o mesmo comportamento do JFormattedTextField.

O que acham?!

>>>> Continuando meu post <<<<

Conversando aqui com um amigo na empresa tudo ficou mais claro!

O que acontece na verdade é que String é o único objeto IMUTÁVEL. No caso de String o que eu pretendia fazer nunca seria possível mesmo.

No caso dos demais objetos, o que eu pretendo é possível, mas não usando "=" pra atribuir valor. Posso fazer isso usando métodos do objeto, e ai sim funciona, como no caso do JFormattedTextField que eu usei o .setText(). No caso do Integer eu tb. não consegui pq ele não tem um ".setValue()" (por ex) pra que eu possa atribuir valor sem usar o "=".

Quando eu uso o "=" ele internamente está fazendo um "new meuObjeto", e por isso ele perde a referência ao objeto inicial, já que ele cria um novo objeto.

Gente! Brigada pelos posts, juntei tudo e consegui entender. Vlw! :wink:

Você tá confundindo um pouco as coisas.

Uma coisa é você atribuir a uma variável de referência um obj. Outra coisa é você pegar uma var de referência, no caso para o JFormattedTextField, e chamar um método setter. Nesse caso o estado do obj foi alterado, por isso que muda a String que você passa.

No caso que você passa a String você redefine o valor da variável, local ao método diga-se de passagem, essa vai referenciar um outro objeto (“Sou B”) e isso não influencia em nada a variável que você tinha definido anteriormente (“Sou A”) e passado o valor dela como parâmetro.

Entendeu?

[]`s

sic entendi sim!

Eu tava editando meu post anterior enquanto vc escreveu.
Vlw! :wink:

[quote=ViniGodoy]É isso mesmo. A passagem é por valor.

Em caso de objetos, onde as variáveis são referências, a referência é copiada.

Isso significa que, dentro de um método, embora seja possível alterar valores dentro do objeto referenciado, é impossível alterar para onde essa referência aponta. Se fizer isso, estará alterando só em escopo local.

Ou seja, comandos como:

s.setValue("xuz"); //Ok, s ainda aponta para o objeto fora da função

//Ops, alteramos a referência de S. 
//Isso só vale aqui dentro da função, já que fora daqui, a referência é outra.

s = new String("xyz"); 
s.setValue("xuz"); //Estamos alterando só o s criado na linha de cima.

//Também não conseguimos tornar o s fora da função nulo. 
s = null;

Só terão efeito dentro do método.[/quote]

Exato.

O metodo local recebe uma copia do padrao de bits da variavel de referência, por isso é possivel alterar o estado do objeto (ambas acessam
o mesmo objeto).

Resumindo: existem 2 referencias ( 1 externa e 1 interna), mas 1 objeto.

É por isso que fazer a referência interna do metodo apontar pra NULL nao torna o objeto elegível para a coleta de lixo. Ainda existe a referência externa.