Criar Metodo clone() Generico

Bom to querendo criar um metodo clone() so q generico… pq pelo jeito vo precisar utilizar em varios lugares…
e n keria ter q colocar em cada POJO esse metodo…
Já queria tratar em lugar soh… exception, casting… enfim…

Tentei mas pra variar neh n deu certo kkk…

Criei essa Classe q vai ser de onde vou chamar…

public class Clone<T> extends Cloneable {
	
	private final Class<T> classe;
	
	public Clone(Class<T> classe) {
		this.classe = classe;
	}
	
	@SuppressWarnings("unchecked")
	public T clone() throws CloneNotSupportedException{
		return (T) super.clone();
	}
	
}

pra poder criar assim mais o menos

Pessoa p = new Pessoa();
		p.setNome("José");
		Pessoa person = new Clone<Pessoa>(Pessoa.class).clone();
		System.out.println(person.getNome());

Mas eu Estou achando que o problema está na hora d dar o super
mas eu n tenho ideia d como fazer isso funcionar…

ai Gera esse Erro

Exception in thread "main" java.lang.CloneNotSupportedException: Unimed.Util.Clone
	at java.lang.Object.clone(Native Method)
	at Unimed.Util.Clone.clone(Clone.java:22)
	at Unimed.Teste.Teste.main(Teste.java:21)

Será q Alguem pode Me Ajudar to perdidao…
MUito Obrigado :smiley:

Olá,

Cara, fiz algumas alterações aqui e até funcionou. Funcionou para clonar a class Clone. Porem, o objeto que tem dentro dela, o Pessoa, nao clona.

class Clone<T> implements Cloneable {

    T t;

    public Clone(T t) {
        this.t = t;
    }

    public T getT()
    {
        return t;
    }

    @SuppressWarnings("unchecked")
    public Clone<T> clone() throws CloneNotSupportedException{
        return (Clone<T>) super.clone();
    }
}

Dei uma olhada na net e tem algo como DeepCopy.
Outra alternativa poderia ser fazer com Reflection.

att,

Então ai q tá neh… o problema acho q tá no super
ele executa na classe q ele tá…

Não é isso. O sem o super entraria em loop.
O problema ai é que Clone que é clonavel, e não o seu objeto.

Pesquisei e achei uma alternativa. Funcionou:

import java.io.*;
import java.util.*;
import java.awt.*;
public class Cloner
{
   // so that nobody can accidentally create an ObjectCloner object
   private Cloner(){}
   // returns a deep copy of an object
   static public Object deepCopy(Object oldObj) throws Exception
   {
      ObjectOutputStream oos = null;
      ObjectInputStream ois = null;
      try
      {
         ByteArrayOutputStream bos =
               new ByteArrayOutputStream(); // A
         oos = new ObjectOutputStream(bos); // B
         // serialize and pass the object
         oos.writeObject(oldObj);   // C
         oos.flush();               // D
         ByteArrayInputStream bin =
               new ByteArrayInputStream(bos.toByteArray()); // E
         ois = new ObjectInputStream(bin);                  // F
         // return the new object
         return ois.readObject(); // G
      }
      catch(Exception e)
      {
         System.out.println("Exception in ObjectCloner = " + e);
         throw(e);
      }
      finally
      {
         oos.close();
         ois.close();
      }
   }

}

class Test{

    public static void main(String[] a) {

        Pessoa p = new Pessoa("Original");

        try{
        Pessoa p1 = (Pessoa) Cloner.deepCopy(p);
        p1.n = "Clone";
        System.out.println(p.n);
        System.out.println(p1.n);
        }
        catch(Exception e)
        {
            e.printStackTrace();
        }
    }
}

class Pessoa implements Serializable
{
    String n;

    public Pessoa(String name)
    {
        n = name;
    }
}

…porém seu objeto tem que ser Serializavel.

Artigo completo -> http://www.javaworld.com/javaworld/javatips/jw-javatip76.html?page=2

Eu Antes de implementar uma solução na parte de um dao generico consegui escapar d por serializable nas classes…
o qto isso pode me prejudicar no meio do projeto caso eu coloke isso nos POJO’s???

Então cara, eu não vejo problema em ter herança com Serializable, ainda mais que trata-se de uma Interface marcadora, ou seja, voce não vai perder usando o extends.
Mas já que voce quer fugir disso, a ultima opção que consigo imaginar é fazer o clone com Reflection.

Este exemplo eu não testei, mas dá uma olhada:

http://www.stupidjavatricks.com/?p=26

OPá!!!
Testei e funcionou!

public static Object clone(Object o)
{
  Object clone = null;
 
  try
  {
     clone = o.getClass().newInstance();
  }
  catch (InstantiationException e)
  {
     e.printStackTrace();
  }
  catch (IllegalAccessException e)
  {
     e.printStackTrace();
  }
 
  // Walk up the superclass hierarchy
  for (Class obj = o.getClass();
    !obj.equals(Object.class);
    obj = obj.getSuperclass())
  {
    Field[] fields = obj.getDeclaredFields();
    for (int i = 0; i < fields.length; i++)
    {
      fields[i].setAccessible(true);
      try
      {
        // for each class/suerclass, copy all fields
        // from this object to the clone
        fields[i].set(clone, fields[i].get(o));
      }
      catch (IllegalArgumentException e){}
      catch (IllegalAccessException e){}
    }
  }
  return clone;
}

kkkkkkkkkkkk… Boa…
Então pq eu achei um topico no Guj… de um cara q tava fazendo com ObjectOutputStream
e talz parecido com akele exemplo q vc me mando…
e tava recriminando talz e utilizava muita memoria com perigo de estourar sei lá…

Mas vc acha q esse com Reflection eh melhor??

valeo acho q ja da pra começar será q com reflection tem como eu pegar as variaveis de instancias do objeto e clonar tb no mesmo metodo???

Acho melhor você adicionar um método em cada POJO. Se seus pojos tiverem um ancestral comum (e não forem tão pojos assim), você poderia colocar o clone lá também.

Afinal, o método é simples assim:

public Pessoa clone() { return (Pessoa) super.clone(); }

Não precisa lançar a exception, já que seu objeto efetivamente é clonável.

E já faz quem programa parar para pensar se só isso é suficiente. Lembre-se que pode ser necessário fazer deep copy de objetos relacionados, e que nada impede que objetos tenham referências circulares.

Geralmente é uma má idéia tratar clonagem ou serialização de maneira genérica e despreocupada no sistema.

ViniGodoy…
Mas mesmo assim tenho q dar um throws no metodo neh…
esse era um detalhe q eu queria evitar…

Tipo Gostaria de tratar tudo isso em 1 lugar soh… neh…

Não, não tem que dar throws no método.

Como vc vai tratar em um lugar só, se cada objeto é diferente?

Você pode mesmo usar reflexão, mas ela insere outros problemas:

  1. Os erros de reflexão ocorrem em Runtime;
  2. Ela não pensará se a cópia que está fazendo faz sentido ou não;
  3. Você deverá tratar manualmente casos de referências circulares;

Ainda acho melhor escrever 3 linhas a mais por POJO (nem é muita coisa), e manter seu programa seguro na compilação e uma obrigação do seu programador pensar no que está fazendo.

A única coisa chata é que realmente você ainda precisará fazer “implements Cloneable” no topo da sua classe.

ueh então to fazendo algo de errado…

public Usuario clone(){
		return (Usuario) super.clone();
	}

Por exemplo… ele marca o super.clone com “Unhandled exception type CloneNotSupportedException”

É verdade, vc terá que fazer um try catch.

public Usuario clone(){ try { return (Usuario) super.clone(); } catch (CloneNotSupported e) {} }

Ainda é melhor que o throws, pois aí quem usa a classe poderá fazer:

Usuario u2 = u1.clone();

Sem ter que capturar exception alguma.

Estranho eu tava fazendo um teste aki… e não implementei Cloneable… e mesmo assim funcionou…
POr que Será?

No meu sistema, os Pojo’s tem um ancestral em comum, que é o Entity. Este implementa Serializable. Assim, todos os Pojo’s são clonáveis.
E é como disse: não acho que seja um problema implementar uma interface marcadora.

[quote=colored]Estranho eu tava fazendo um teste aki… e não implementei Cloneable… e mesmo assim funcionou…
POr que Será?[/quote]

Testou com o Reflection?

Sim Testei. Com Reflection…

Eh q nao tinha percebido meu codigo e achei q estava usando o clone();

agora fica a duvida… pq c for colocar esse metodo em todos os pojos vai ser tenso… pq tem bastante aki no sistema…

agora com reflection ta no eskema já, já ta tratada a exception… so precisar fazer o casting mesmo…
em relação ao uso eu teria que clonar as variaveis de instacia tb… então qto 1 qto o otro daria na mesma…

Acho que esta forma é também interessante.

[code]public class MinhaClasse{
// outros contrutores
public MinhaClasse(MinhaClasse c){
/* entre aqui com a logica de clonagem, tipo
this.atributo = c.getAtributo(); */
}
// o resto da minha classe…
}

MinhaClasse clone = new MinhaClasse(objetoASerClonado);
[/code]