[RESOLVIDO] Problemas na referência de objetos

25 respostas
K

Galera,

Então, estou com um problema que acredito ser iniciante, apesar de já programar há um tempo e nunca ter acontecido isso comigo. hehehe!

Observem esse código:

Telefone telefone;

telefone = new Telefone();
telefone.setNumero("88888888");
System.out.println(telefone);
System.out.println(telefone.getNumero());
		
telefone = new Telefone();
telefone.setNumero("12345678");
System.out.println(telefone);
System.out.println(telefone.getNumero());

Quando compilo, sai o seguinte resultado:

br.com.sistema.entity.Telefone@1f
88888888
br.com.sistema.entity.Telefone@1f
12345678

O problema é o seguinte, eu estou jogando essas duas referências em um ArrayList (posteriormente), porém, como a referência está saindo com a mesma identificação (br.com.sistema.entity.Telefone@1f), eu não consigo usar o método “indexOf(objeto)”, ou o “remove(objeto)”.

Como eu estou dando “New” na variável “telefone”, não era para ele estar criando uma nova referência (Por ex: br.com.sistema.entity.Telefone@3b78dsf) ?

Valeu!!!

25 Respostas

nel

Sim, você consegue. É apenas como se você estivesse dando um telefone.toString().
São referências distintas, pode adicionar a sua list sem problemas e utilizar os métodos que desejar.

Este formato é apenas o formato em String do seu Objeto Telefone.
Abraços.

evertonsilvagomesjav

Kired bom d mais? Vc tem que fazer uma subscrita do metodo toString() da classe Object na sua Classe, para poder exibir o conteudo do seu Objeto.

K

Opa,

Valeu pelas respostas, galera!!!

Mas o problema é que quando eu chamo o método “remove(objeto)”, ou “indexOf(objeto)”, ele não acha o objeto correto, ele remove o primeiro objeto da lista, mesmo que o objeto que eu mande seja na verdade o quinto ou sexto da lista, ou no caso do indexOf, ele sempre retorna o ID: 0 . Sinceramente, não entendo o por que disso… hehehe!

Quanto ao toString(), que eu saiba, se eu não reescrever ele, ele retorna o ID do objeto na memória, por isso que eu acho que deveriam vir números diferentes ali, e não os mesmos. Me corrijam se eu estiver errado.

Valeu!!!

evertonsilvagomesjav

na realidade o toString() retorna o objeto em questão, no seu caso o objeto telefone.

se vc fizer isso:

telefone.setNumero("12345678");   
System.out.println(telefone);

E nao tiver um toString() subscrito vc vai receber o proprio resultado que vc sitou, agora se vc quiser imprimir o conteudo do objeto em Strings, como por exemplo o numero ai vc teria que fazer a subscrita como por exemplo:

public String toString(){

return "Numero do telefone" +numeroTelefone;
 
}
A

adicione no ArrayList o “getNumero.toString()
ex: arrayListExemplo.add(telefone.getNumero().toString())
Funciona perfeitamente …

K

Opa,

Agradeço novamente as respostas!

Mas meu problema é o seguinte:

Eu entendo a utilidade do “toString()”, porém, não é minha intenção altera-lo agora.

Eu criei um ArrayList de telefones mesmo:

List<Telefone> telefones = new ArrayList<Telefone>

e vou adicionando os telefones, no caso, aqueles dois que eu criei por exemplo:

Telefone telefone;

telefone = new Telefone();
telefone.setNumero("88888888");
System.out.println(telefone);
System.out.println(telefone.getNumero()); 

telefones.add(telefone); //adicionei o "Objeto 1"
          
telefone = new Telefone();  
telefone.setNumero("12345678");  
System.out.println(telefone);  
System.out.println(telefone.getNumero());

telefones.add(telefone); //adicionei o "Objeto 2"

O problema disso é o seguinte:

Eu estou trabalhando em uma página jsf, em que uma Pessoa (classe), pode ter vários telefones (Classe Telefone). Para isso, criei uma parte da página em ajax que vai adicionando telefones a lista de telefones.

Quando e cada telefone que o cara adiciona, ele chama o seguinte método:

public void salvaTelefone() {
       colaboradorInEdit.getTelefones().add(telefone);
       this.telefone = new Telefone();
}

Porém, quando vou remover um telefone dessa lista, por exemplo, eu uso um a tag <f:setPropertyActionListener> do JSF, que joga um objeto selecionado ao ManagedBean. Eu fiz testes, e vi que ele está jogando o objeto correto, porém, quando ele vai remover esse objeto da lista, ele remove sempre o primeiro objeto da lista (na posição 0), como se fossem todos objetos iguais, com a mesma referência na memória.

Não sei se fui claro, eu evitei explicar o meu problema desde o início porque é meio grande mesmo, hehehehe, mas acho que não estava me expressando muito bem…

Valeu, Galera!

nel

Se a cada vez que você adiciona um Telefone você cria uma nova instância do seu Objeto, não haverá problemas de referência, ou seja:

Telefone telefone = new Telefone(); list.add(telefone);

Você pode adicionar isso a um Loop sem problemas que não vai sobrescrever seu objeto telefone, sempre será criado (instanciado) um novo. Se fizer dessa forma e adicionar 3 objetos ao list e depois der:

//posição 3, já que List inicia em 0 list.remove(2);
Você removeu o objeto 3. O que pode estar acontecendo é um erro na forma como implementou a remoção.
Abraços.

evertonsilvagomesjav
Telefone telefone;   
  
telefone = new Telefone();   
telefone.setNumero("88888888");   
System.out.println(telefone);   
System.out.println(telefone.getNumero());   
  
telefones.add(telefone); //adicionei o "Objeto 1"   
             
telefone = new Telefone();     
telefone.setNumero("12345678");     
System.out.println(telefone);     
System.out.println(telefone.getNumero());   


telefones.add(telefone); //adicionei o "Objeto

Humm, pelo que eu to vendo se vc ta usando o mesmo objeto pra setar o telefone ele vai somente reescrever o telefone, esse metodo seu teria que estar dentro de um loop ou entao vc criar um novo objeto.

nel

Everton, engano seu amigo. Ele somente usa a mesma variavel mas cria uma nova referência, já que ele utiliza novamente o new, concorda comigo? :slight_smile:

O que ele fez seria o mesmo que a um loop, digamos assim:

for(int i =0; i<10; i++){ Telefone telefone = new Telefone(); }

Variavél com o mesmo nome mas com referência distintas. A questão é como ele está implementando o remove mesmo.
Abraços.

evertonsilvagomesjav

nelll olho de aguia kkk agora que eu vi rsrs, certo vc amigo!!

pmlm

Errado. Ele está a fazer new, logo a criar um novo objecto. Aparentemente não vejo qualquer problema no código para provocar essa situação.

K

@nel
Realmente, se eu passar direto o número da posição, ele remove corretamente. O problema é que eu não tenho como passar o número da posição, eu só posso passar o objeto diretamente e é ai que ta rolando o problema, pois, pelo que parece, os objetos estão com a mesma referencia.

@evertonsilvagomesjava
É engraçado, pois eu consigo listar esse Array, e ele mostra todos os objetos certinho. Se eu selecionar um deles e dar um “telefones.get(2)”, ele tras o telefone correto. Porém, como todos os objetos parecem ter a mesma referência (não sei como acontece isso, pois se eles tivessem a mesma referência mesmo, era para reescrever os valores do objeto já criado, e não criar um novo objeto), eu não consigo utilizar o método “telefones.remove(objeto)”, nem o “telefones.indexOf(objeto)” ( Ele retorna sempre zero, pois a referencia é a mesma em todos os objetos).

É bem estranho isso, ta meio fora do que eu conheço na teoria do Java. hehehe!

Valeu novamente, pessoal!!!

K

@pmlm
Exatamente. Por isso não entendo o que está acontecendo. Já cheguei a achar que fosse problema do Eclipse, ou da JVM, mas sei lá, to o dia inteiro tentando desvendar esse problema. hehehe!

nel

Que isso Everton! hehe…

Kired, se está enviando um único objeto, faça assim amigo:

int index = suaLista.indexOf(telefone); suaLista.remove(index);

Ok?

Abraços.

K

@nel
Então, já tentei isso, não funcionou também. Até porque eu acho que o próprio método “remove(objeto)”, faz isso internamente, usa o “indexOf” primeiro para depois remover.

A variável “index” vem com o valor 0, pois, apesar de todos os objetos da lista possuirem valores diferentes nos seus atributos, eles tem o mesmo valor de referencia (dando um “toString()”, vem a mesma referencia).

É tão verdade que todos os objetos estão com a mesma referencia, que se eu utilizar o método “lastIndexOf”, ele retorna o último objeto da lista. hehehe!

Loucura total!

Agradeço a resposta de todos!

Vou continuar procurando uma solução “teórica” pra isso.

Valeu!!!

pmlm

Como é a classe Telefone? Implementaste o equals/hashCode?

nel

Amigo, ai o problema já está sendo outro. A questão é como você está efetuando isso. Se usar da forma como indiquei é para funcionar, agora, tudo depende da forma como você está fazendo isso.

Se está utilizando JSF é para o seu Objeto chegar preenchido ao seu método remover e nele você remove o Objeto.
Se tentar efetuar testes da forma como está fazendo realmente não vai funcionar. Crie assim, por exemplo:

Telefone telefone = new Telefone();
//seus setters

Telefone t = new Telefone();
//seus setter

Se enviar o t ou telefone para buscar o indice na lista ele com absoluta certeza vai encontrar o Objeto correto, mas, se enviar valores distintos do Objeto mas com a mesma variavél de referência, ele sempre vai buscar o primeiro item. Sendo sincero, acho que você está fazendo uma "Tempestade em um copo d'agua", ou seja, está complicado o que é simples.

Abraços.

K

@pmlm
Olha, me perguntando isso, me chamou a atenção pro hashCode(), será que isso tem a ver?

Porque, na verdade, o equals() e o hashCode() estão baseados no “id” da classe Telefone, mas como ela ainda não foi persistida, esse id é nulo, então não tem como diferenciar uma classe da outra pelo “equals()”.

Será que é isso?

Valeu! Abraços!

@Entity
@Table(name = "TELEFONE")
public class Telefone implements Serializable {

	private static final long serialVersionUID = -5765740267067209499L;

	@Id
	@GeneratedValue(strategy = IDENTITY)
	private Long id;
	
	@Column(name = "ddd")
	private String ddd;
	
	@Column(name = "numero")
	private String numero;
	
	@Column(name = "ramal")
	private String ramal;
	
	@Enumerated(EnumType.STRING)
	private TipoTelefone tipoTelefone;

	public Telefone(){

	}

	public Long getId() {
		return id;
	}

        //getters & setters...

	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + ((id == null) ? 0 : id.hashCode());
		return result;
	}

	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		Telefone other = (Telefone) obj;
		if (id == null) {
			if (other.id != null)
				return false;
		} else if (!id.equals(other.id))
			return false;
		return true;
	}
	
}
nel

Só para deixar claro uma coisa:

Seu Object: Telefone.
Sua referência: telefone (no seu caso)

Mesmo que você sempre dê new, a referência ao Objeto será sempre a mesma mas como há instâncias distintas ele é capaz de armazenar valores distintos, entendeu? :slight_smile:

jgbt

cara,
quando vc chama o metodo remove de uma collection passando um objeto como parametro. internamente vai ser verificado
se existe algum objeto igual ao passado como parametro. se existir ele vai ser removido. Como ele faz isso?
Chamando o metodo equals de cada objeto na collection passando o objeto recebido como parametro.
Agora a pergunta:
Como se sabe que 2 objetos telefone são iguais?
A jvm vai advinhar? user telepatia? :smiley:

Entao sua resposta esta no metodo equals.

[]´s

K

@nel
Realmente, provavelmente irá funcionar desta maneira. O problema é que eu não tenho como criar uma variável para cada número, já que eu não sei quantos números o cara vai adicionar. Eu não posso deixar isso dessa maneira estática.

Então eu uso a mesma variável e vou criando novos objetos pra ela a medida que o cara vai clicando em “Adicionar Telefone”, só que ai ta dando esse problema que, teoricamente, não era para acontecer.

Valeu!

K

@jgbt
É isso mesmo. hehehe!

O método equals está implementado, mas está implementado por um atributo que ainda não foi preenchido, já que ele é gerado somente quando persistido.

Então como o id sempre é nulo (até que seja persistido), todos os objetos são “iguais”, e acaba rolando esse problema.

Agora como eu vou fazer pra resolver isso (já que, pelo padrão da JPA, o hashCode e o equals tem que ser baseado no id), eu não faço idéia. Mas ai eu me viro. Pelo menos já deu pra descobrir o problema. hehehe!!!

Valeu, Galera! Brigadão mesmo!

Abraços!

pmlm

Exactamente por isso perguntei. Se ele achava que eram iguais é porque tu de alguma forma estavas a dizer que eram iguais :slight_smile:
Infelizmente ele tem sempre razão

K

É verdade. hehehe! Por um momento, eu achei que ele pesquisasse o objeto usando o sinal de comparação mesmo:

objeto == objeto

Assim eu acredito que iria funcionar, pois, o JSF manda exatamente o mesmo objeto que está na lista, acredito eu.

Abraços!

K

Galera,

Vou deixar registrada aqui a idéia que eu tive pra resolver esse problema, caso alguém tenha o mesmo (estar usando JPA, JSF, e usar o equals somente para id, que ainda é nulo).

//variáveis só para exemplificar melhor
private List<Telefone> telefones = new ArrayList<Telefone>();
private Telefone telefone;

public void removeTelefone() {
	for (int i = 0; i < telefones.size(); i++) {
		if (telefone == telefones.get(i)) {
			telefones.remove(i);
		}
	}
	telefone = new Telefone();
}

Na tag “<f:setPropertyActionListener>” do JSF, ele manda exatamente o mesmo objeto, então permite você comparar dois objetos usando:

objeto == objeto

Sei que ficou meio gambiarra, mas foi a solução que me veio a cabeça por agora, hehehe!

Valeu a ajuda ae, Galera!!!

Abraços!!!

Criado 26 de novembro de 2009
Ultima resposta 26 de nov. de 2009
Respostas 25
Participantes 6