Copiar listas problema nos endereços

Boas, estou com um problema tenho 2 listas, ao copiar uma lista para a outra :

for(Disciplinas d2: discplinas)
discplinas_temp.add(d2);

Estou copiando a lista disciplinas para a lista disciplinas temp, até ai tudo bem, o problema é quando eu faço por exemplo:

for(Disciplinas d: discplinas_temp)
d.set_tempo(0);

Ele aqui altera-me o tempo para 0 nas 2 listas, pois o endereço ficou o mesmo, como faço para resolver esse problema, alterando apenas na lista das discplinas_temp ?
Cumprimentos

Isso ocorre porque vc está alterando o mesmo objeto… a lista só tem a refência para o objeto e não o objeto em si, quando vc “copia” para a outra lista, vc esta copiando a referencia para o objeto, ou seja, ambas listas terão referência para o mesmo objeto, alterando ele, vai alterar nas duas.

para resolver isso, vc tem que adicionar uma cópia do objeto na outra lista, e para criar essa cópia vc usa o método clone de Object… mas para isso funcionar seu objeto disciplina tem que implementar Cloneable:

http://java.sun.com/j2se/1.5.0/docs/api/java/lang/Cloneable.html

e sobrescrever esse método clone de Object (conforme a documentação)

http://java.sun.com/j2se/1.5.0/docs/api/java/lang/Object.html#clone()

se sua classe tiver atributos que são outros objetos, esses objetos também tem que ser Cloneable e assim por diante, até obter um “clone” de tudo que precisa, ai vc vai ter um outro objeto idêntico ao primeiro na memória, e esse pode alterar tranquilo.

E seu método add ficaria assim:

		for (Disciplina d2 : discplinas) {
			try {
				discplinas_temp.add((Disciplina) d2.clone());
			} catch (CloneNotSupportedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}

ps: apriveita e ja troca o nome do seu objeto Disciplinas para Disciplina (sem o S), ja que provavelnente uma instancia desse objeto não representa varias disciplinas e sim apenas uma certo?!

flw

Obrigado luBS mas ainda estou com problemas, ele não está reconhecendo o d2.clone()); já agora como fica a Classe Disciplina ? (Pode dar -me um exemplo ) obrigado!

Obrigado!

[quote=“luBS”]Isso ocorre porque vc está alterando o mesmo objeto… a lista só tem a refência para o objeto e não o objeto em si, quando vc “copia” para a outra lista, vc esta copiando a referencia para o objeto, ou seja, ambas listas terão referência para o mesmo objeto, alterando ele, vai alterar nas duas.

para resolver isso, vc tem que adicionar uma cópia do objeto na outra lista, e para criar essa cópia vc usa o método clone de Object… mas para isso funcionar seu objeto disciplina tem que implementar Cloneable:

http://java.sun.com/j2se/1.5.0/docs/api/java/lang/Cloneable.html

e sobrescrever esse método clone de Object (conforme a documentação)

http://java.sun.com/j2se/1.5.0/docs/api/java/lang/Object.html#clone()

se sua classe tiver atributos que são outros objetos, esses objetos também tem que ser Cloneable e assim por diante, até obter um “clone” de tudo que precisa, ai vc vai ter um outro objeto idêntico ao primeiro na memória, e esse pode alterar tranquilo.

E seu método add ficaria assim:

		for (Disciplina d2 : discplinas) {
			try {
				discplinas_temp.add((Disciplina) d2.clone());
			} catch (CloneNotSupportedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}

ps: apriveita e ja troca o nome do seu objeto Disciplinas para Disciplina (sem o S), ja que provavelnente uma instancia desse objeto não representa varias disciplinas e sim apenas uma certo?!

flw[/quote]

Mas você viu a assinatura do método clone de Object?! ele eh protected, ou seja, se tiver em pacote diferente de Object (e com certeza está) ele só pode ser invocado de dentro de uma classe filha (e vc provavelmente esta tentando invocar de outra classe). Então tem que reescrever clone() dando mais privilégios, ou seja, coloca ele como public.

Segue um código de exemplo:

import java.util.ArrayList;
import java.util.List;

public class Teste {

	static class Disciplina implements Cloneable {

		private String nome;

		public String getNome() {
			return nome;
		}

		public void setNome(String nome) {
			this.nome = nome;
		}

		@Override
		public Object clone() throws CloneNotSupportedException {
			// TODO Auto-generated method stub
			return super.clone();
		}

	}

	public static void main(String[] args) {
		List<Disciplina> discplinas = new ArrayList<Disciplina>();
		List<Disciplina> discplinasTemp = new ArrayList<Disciplina>();

		Disciplina d = new Disciplina();
		d.setNome("teste");
		discplinas.add(d);
		
		for (Disciplina disc : discplinas) {
			try {
				discplinasTemp.add((Disciplina) disc.clone());
			} catch (CloneNotSupportedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		
		for (Disciplina disc : discplinasTemp) { 
			disc.setNome("modificado");
		}
		
		for(Disciplina disc : discplinasTemp) {
			System.out.println(disc.getNome());
		}		
		
		for(Disciplina disc : discplinas) {
			System.out.println(disc.getNome());
		}

	}

}

Repare que eu não fiz nada no método clone, apenas chamei o super dele, partindo do que está escrito na documentação desse método:

ps: String eh um immutable object
http://www.javapractices.com/Topic29.cjp